views:

937

answers:

3

I have an issue that seems like very flaky behavour, is this a problem with Ruby or something I've done? Please help - my project is stalled until I resolve this.

Given this code running on Mac OS Leopard:

require 'uri'
require 'net/ssh'
require 'net/sftp'
include Net

def copy_from_uri( uri, local_path )
    # SFTP copy
    SFTP.start( uri.host, uri.user, :password => 'password' ) do |sftp|
     puts "downloading from #{uri.host}, path #{uri.path}\n"
     sftp.download( uri.path, local_path )
    end
end

remote_uri = URI.parse( "sftp://example.com/test.mp4" )
local_file = "/tmp/remote_copy_test.mp4"
result = copy_from_uri( remote_uri, local_file );

What would cause the following error?

$ ruby sftp_fail.rb 
/Library/Ruby/Site/1.8/net/sftp.rb:43:in `start': undefined method `shutdown!' 
for nil:NilClass (NoMethodError)
    from sftp_fail.rb:8:in `copy_from_uri'
    from sftp_fail.rb:18

FYI I've set RUBYOPT correctly so gems are loaded and my gems are up-to-date, according to:

$gem list --local
net-sftp (2.0.2, 1.1.0)
net-ssh (2.0.15, 1.1.2)
+2  A: 

It is telling you that some object which you are attempting to call the shutdown! method on is nil. Now, that code is not in your example, so it is hard to say why that would be, but I highly doubt it is a bug in the language.

It is happening in this method call, so perhaps you can post that code?

result = copy_from_uri( remote_uri, local_file );

URI#parse should never return nil (it would throw an exception), so it would help to see that method body if possible.

Ed Swangren
Yep. uri.user was nil, because I forgot to use the format "sftp:://[email protected]". It took me a while to sort out the RUBYOPT issue, hence the allegation of an internal issue.
Justicle
So... this was the answer then, no? :)
Ed Swangren
Definitely a problem caused by passing a value that was nil, in my case I hadn't updated my variables to my new format @ip should have been @host.name
Vertis
+1  A: 

I've just encountered this, but it was caused by another reason. My file host had changed their RSA key, so the key in ~/.ssh/known_hosts was incorrect --- this resulted in the same error as shown, filtered up from SSH. Deleting the invalid key fixed the problem.

Mike
A: 

This error is actually due to a bug in net-sftp v2.0.2:

def self.start(host, user, options={}, &block)
  # ...
rescue Object => anything
  begin
    session.shutdown!
  rescue Exception
    # swallow exceptions that occur while trying to shutdown
  end

  raise anything
end

When an error occurs in the #start method, it attempts to shutdown the session...but if session itself is nil, it'll raise NoMethodError. The rescue Exception line attempts to swallow all exceptions but it is actually rescuing Net::SFTP::Exception rather than the root-level Exception. This has been recently fixed (see this commit).

Upgrade to net-sftp 2.0.4 and you'll no longer get this obscure error. You'll still get an error, but it should be more helpful now that the original error isn't being discarded by a new error happening in a rescue block.

Myron