Rbenv: Your Ruby version is 1.9.3, but your Gemfile specified 2.0.0

Created on 30 May 2013  路  21Comments  路  Source: rbenv/rbenv

I'm trying to run a rake task on a rails app, and am getting this error:

/home/vagrant/.rbenv/versions/2.0.0-p195/lib/ruby/gems/2.0.0/gems/bundler-1.3.5/lib/bundler/definition.rb:361:in     `validate_ruby!': Your Ruby version is 1.9.3, but your Gemfile specified 2.0.0 (Bundler::RubyVersionMismatch)
    from /home/vagrant/.rbenv/versions/2.0.0-p195/lib/ruby/gems/2.0.0/gems/bundler-1.3.5/lib/bundler.rb:116:in `setup'
    from /home/vagrant/.rbenv/versions/2.0.0-p195/lib/ruby/gems/2.0.0/gems/bundler-1.3.5/lib/bundler/setup.rb:17:in `<top (required)>'
    from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
rake aborted!

As you can see from the paths in the error though, I am running 2.0.0:

$ ruby -v
ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-linux]

$ bundle -v
Bundler version 1.3.5

$ gem env
RubyGems Environment:

  • RUBYGEMS VERSION: 2.0.3
  • RUBY VERSION: 2.0.0 (2013-05-14 patchlevel 195) [x86_64-linux]
  • INSTALLATION DIRECTORY: /home/vagrant/.rbenv/versions/2.0.0-p195/lib/ruby/gems/2.0.0
  • RUBY EXECUTABLE: /home/vagrant/.rbenv/versions/2.0.0-p195/bin/ruby
  • EXECUTABLE DIRECTORY: /home/vagrant/.rbenv/versions/2.0.0-p195/bin
  • RUBYGEMS PLATFORMS:

    • ruby

    • x86_64-linux

  • GEM PATHS:

    • /home/vagrant/.rbenv/versions/2.0.0-p195/lib/ruby/gems/2.0.0

    • /home/vagrant/.gem/ruby/2.0.0

  • GEM CONFIGURATION:

    • :update_sources => true

    • :verbose => true

    • :backtrace => false

    • :bulk_threshold => 1000

  • REMOTE SOURCES:

I tried doing rbenv global 2.0.0-p195, but that didn't help. Looks like it might be trying to use system ruby instead of rbenv for some reason?

Raised an issue with bundler: https://github.com/bundler/bundler/issues/2489 but it seems to be an rbenv issue.

rake is a rbenv shim at: ~/.rbenv/shims/rake

Thanks,

Ian

Most helpful comment

@ichilton If you have a Rake task that is forking off a subprocess to run a command like heroku and if your rake parent process is bundler-aware (i.e. you ran bundle exec rake), then all subprocesses will inherit rake's ENV.

In Bundler::Runtime#setup_environment, Bundler sets some environment variables, the most important being ENV['RUBYOPT'] which is used by and ruby processes down the line. The implication being that your subprocess command (sh "heroku") is effectively being invoked like:

BUNDLE_GEMFILE=/path/to/Gemfile ruby -rbundler/setup -S heroku.

So what do you do when you want to bust out of Bundler's bubble for subprocesses? Nuke some ENV keys around the subprocess. In the busser gem, I'm dealing with it this way and Bundler itself has a Bundler.with_clean_env. There was a reason I didn't go with Bundler.with_clean_env but can't remember why. Assuming that it works (and looks like it should):

# Rakefile
task :freedom do
  Bundler.with_clean_env { sh "heroku" }
end

That should help the embedded/vendored Ruby in the Heroku Toolbelt to be invoked in a less tainted way. Hope this helps, this is thorny stuff!

All 21 comments

It's not system ruby since the stack trace comes from:

/home/vagrant/.rbenv/versions/2.0.0-p195/lib/ruby/gems/2.0.0/gems/bundler-1.3.5

which clearly indicates that you're running 2.0. I would rather believe this is a bug with Bundler's version check.

Ok, thanks.

They are saying:

Well, as you can see from the backtrace you originally posted here, you
are somehow loading the Bundler installed into Ruby 2... From the
Rubygems installed for 1.9 in /usr/lib. Bundler is correct that you're
running it on the wrong version of ruby.

OK, let us see your rbenv which bundle. What happens when you run just bundle install? And for your original error, what is the exact command you ran? Do you have any plugins?

rbenv hooks rehash
rbenv hooks exec

$ rbenv which bundle
/home/vagrant/.rbenv/versions/2.0.0-p195/bin/bundle

bundle install does the usual Using x (x.x.x) stuff.

The command i'm running is:

$ bundle exec rake prod_data

The part of the rake task mentioned in the stack trace (see below) is:

46    open('db/dumps/pgsql-production.dump', 'wb') do |file|
47       file << open(url).read
48    end

$ ls ~/.rbenv/plugins/
rbenv-use rbenv-whatis ruby-build

I only had ruby-build when I first had this problem - I installed rbenv use to see what happened if I manually selected ruby-2.0.0 instead of letting .ruby-version in my project directory switch it.

I've just tried running those two hooks commands and get the same error:

$ bundle exec rake prod_data
Downloading PostgreSQL data from production (latest snapshot)
/home/vagrant/.gem/ruby/2.0.0/gems/bundler-1.3.5/lib/bundler/definition.rb:361:in `validate_ruby!': Your Ruby version is 1.9.3, but your Gemfile specified 2.0.0 (Bundler::RubyVersionMismatch)
    from /home/vagrant/.gem/ruby/2.0.0/gems/bundler-1.3.5/lib/bundler.rb:116:in `setup'
    from /home/vagrant/.gem/ruby/2.0.0/gems/bundler-1.3.5/lib/bundler/setup.rb:17:in `<top (required)>'
    from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
rake aborted!
No such file or directory - 
/vagrant/myproj/lib/tasks/prod_data.rake:47:in `block (3 levels) in <top (required)>'
/vagrant/myproj/lib/tasks/prod_data.rake:46:in `block (2 levels) in <top (required)>'
Tasks: TOP => prod_data => prod_data:pgsql => prod_data:download_pgsql
(See full trace by running task with --trace)

It seems like everything is in order, from your end, but that the rake task spawns a Ruby subprocess somewhere with system ruby (/usr/bin/ruby). We can't know where this happens without seeing your full rake task code. You'll have to dig deeper.

Does any executable you start has a shebang #!/usr/bin/ruby? Do you use any 3rd party code in your rake task? With rbenv, even if your main rake process started a ruby process in a subshell, it would use the same Ruby version as the main process (2.0), not the system ruby.

Thanks for the reply - that was the theory I ended up at too. I'm just going to go through the task and see if I can see/debug what the problem is.

Thanks,

Ian

When in doubt, check the PATH before shelling out.

$stderr.puts ENV["PATH"]

Found the problem.... i'm shelling out to the heroku command in the rake task - which comes from Heroku Toolbelt.

However, at the top of /usr/bin/heroku is this shebang:

#!/usr/bin/env ruby1.9.1

and sure enough:

$ruby1.9.1 -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]

So that makes sense - except why is bundler complaining? - where does bundler come in when a rake task is calling that executable?

What would you advise as the best fix? - I don't want to change /usr/bin/heroku as that's written by their toolbelt installer and will get upgraded from time to time.

Do I need to prefix the call in the rake task with something to send it through rbenv/bundler?

(although some people here use rvm on mac and some rbenv on vagrant, so actually I wouldn't want to hard code rbenv...is there a way of executing that in a proper shell which has read the profile?)

I'm just using backticks (heroku .....) to execute it at the moment.

Thanks,

Ian

@ichilton If you have a Rake task that is forking off a subprocess to run a command like heroku and if your rake parent process is bundler-aware (i.e. you ran bundle exec rake), then all subprocesses will inherit rake's ENV.

In Bundler::Runtime#setup_environment, Bundler sets some environment variables, the most important being ENV['RUBYOPT'] which is used by and ruby processes down the line. The implication being that your subprocess command (sh "heroku") is effectively being invoked like:

BUNDLE_GEMFILE=/path/to/Gemfile ruby -rbundler/setup -S heroku.

So what do you do when you want to bust out of Bundler's bubble for subprocesses? Nuke some ENV keys around the subprocess. In the busser gem, I'm dealing with it this way and Bundler itself has a Bundler.with_clean_env. There was a reason I didn't go with Bundler.with_clean_env but can't remember why. Assuming that it works (and looks like it should):

# Rakefile
task :freedom do
  Bundler.with_clean_env { sh "heroku" }
end

That should help the embedded/vendored Ruby in the Heroku Toolbelt to be invoked in a less tainted way. Hope this helps, this is thorny stuff!

Thank you Fletcher! - i've actually just come across the same thing here: https://github.com/bundler/bundler/issues/2355 so am going to try that now!

@fnichol Pretty epic answer. Thanks!

Closing this since it's not a bug.

Just to confirm this, changing the shell calls to the following fixed the problem:
Bundler.with_clean_env { sh "cmd" }

Thanks guys.

Thanks!

@fnichol Thanks! :thumbsup:

Thank you @fnichol

@fnichol this was awesome to come across. Yet another thanks!

Thanks @fnichol, this helped me solve a related problem. Basically that I should never run bundle exec heroku, but always heroku instead. Or ensure that I have installed the heroku-toolbelt via brew, and not the official site (and packaged installer). Installing with brew links the heroku CLI ruby version (heroku --version) to the one I've set with RVM (rvm current).

@fnichol exactly what I was looking for. Thanks!

This is the thread that keeps on giving!

gif-keyboard-6922171368322717703

Upgrade Ruby version

Login as root

Install needed packages
apt-get -y install build-essential zlib1g-dev libssl-dev libreadline6-dev libyaml-dev

cd /tmp

Download appropriate ruby version https://www.ruby-lang.org/en/downloads/
wget http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz

Unpack downloaded package
tar -xvzf ruby-2.1.2.tar.gz
cd ruby-2.1.2/

Compile from source
./configure --prefix=/usr/local
make
make install

Was this page helpful?
0 / 5 - 0 ratings