Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Having Rails 2.3pre or Rack 1.1 installed breaks Rails 2.x

#4031

Rails 2.x and earlier currently specifies 'rack ~> 1.0.0' as gem dependency. This can cause problems in the following environment:

  • Thin is installed with RubyGems.
  • Rails 2.x is installed with RubyGems.
  • Rails 3.0pre is installed with RubyGems (which pulls in Rack 1.1).

Thin has a dependency on 'rack', no specific version. However if Rack 1.1 is installed then starting Thin will automatically activate the latest version of Rack, 1.1. Rails's environment.rb tries to activate the Rails gems, but this fails at activating Rack 1.0.x because 1.1 is already activated.

Furthermore, boot.rb mistakenly thinks that this error means Rails isn't installed, so you get a console output like this:

[hongli@Minato foobar.test]$ thin start -S `pwd`/thin.sock -e production
 >> Using rails adapter
Missing the Rails 2.3.5 gem. Please `gem install -v=2.3.5 rails`,
update your RAILS_GEM_VERSION setting in config/environment.rb for the
Rails version you do have installed, or comment out RAILS_GEM_VERSION to
use the latest version installed.

The offending code is in boot.rb's load_rails_gem:

def load_rails_gem
  if version = self.class.gem_version
    gem 'rails', version
  else
    gem 'rails'
  end
rescue Gem::LoadError => load_error
  $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
  exit 1
end

If we put a 'puts load_error' in the rescue block then we'll see that the actual error is something along the lines of:
can't activate rack (~> 1.0.0, runtime) for ["actionpack-2.3.5", "rails-2.3.5"], already activated rack-1.1.0 for ["thin-1.2.5"]

Phusion Passenger is suffering from the same problem since it specifies Rack as a gem dependency too.

This problem can be solved by changing Rails's Rack dependency to "rack >= 1.0.0".

Reported by Hongli Lai · February 22nd, 2010 @ 09:43 AM

State: wontfix
Milestone: none
Assigned to: nobody
Importance: Low

Activity

  1. Maximilian Schulz
    Maximilian Schulz

    I am not sure about the way thin is handling the problem, but I had the same with Passenger. I use the past tense, as the problem can be solved by removing the config.ru file from your application root. As specified in the passenger 2.2.9 release notes, the default behavior was changed. Specifically, passenger's rails adapter priority is now lower than the default rack adapter's. But be removing the config.ru file, the rails adapter will kick in and will load rack 1.0.1 and your rails 2.3.5 apps will load fine again.

    Passenger Configuration:

    • 2.3.5 apps: remove config.ru
    • 3.0.0 apps: keep config.ru

    February 22nd, 2010 @ 10:23 AM

  2. Hongli Lai
    Hongli Lai

    After speaking to Yehuda (http://groups.google.com/group/rubyonrails-core/browse_thread/threa...) and giving it more thought I think the fix should be in RubyGems, not in Rack or in Rails.

    I've considered the possibility of splitting the Rack library into two portions, one that only the web server uses and one that only the web app uses. However this would make it impossible for the web server to modify the app's behavior. For example Thin inserts a middleware that utilizes Rack::Request in order to generate various statistics.

    Phusion Passenger happens to accidentally work around the issue by executing its spawn server without the RubyGems wrapper binary, so it doesn't activate Rack when loading regular Rails apps.

    I think RubyGems should not pre-activate dependencies for which no version specification is given. This would allow Thin to implement an option to tell it which Rack version to load.

    February 22nd, 2010 @ 11:33 AM

  3. Hongli Lai
  4. Saimon Moore
    Saimon Moore

    Is there any other workaround apart from physically modifying rails/actionpack/lib/action_controller.rb?

    April 20th, 2010 @ 12:02 PM

  5. Hongli Lai
    Hongli Lai

    You can modify the Mongrel/Thin/etc startup script to explicitly require Rack 1.0. Phusion Passenger does not need modification and isn't affected by the issue.

    April 21st, 2010 @ 08:50 AM

  6. Saimon Moore
    Saimon Moore

    Hongli, I think I know what happened. I'm using rvm to handle my
    rubies. I have 1.9.1-p378 installed. I also use a gemset for each
    application. Recently I upgraded rvm and had to reinstall all my gems.
    I first installed passenger under 1.9.1 (without a gemset so that
    further minor updates to 1.9.1 wouldn't require updating passenger
    too). Since passenger has a dependency on rack (> 0), it installed
    rack 1.1.0 in the 1.9.1 gemset (which is automatically added to the
    gem path for any sub gem sets. In my application's gemset, I then
    reinstalled rack 1.0.1 not realizing that rack 1.1.0 had been
    installed in the 1.9.1 gemset. You can guess the rest. I've now
    removed rack 1.1.0 gem and it's working fine..

    Thanks...

    It's a pain though all of this. Someone needs to find a decent solution.

    April 21st, 2010 @ 09:23 AM

  7. raggi
    raggi

    Hongli sorry, but there's issues with your RubyGems suggestion, specifically, activation is actually different from require, as activation specifies a specific gem from the gem namespace, whereas require picks arbitrarily from the filesystem space within all gems (ordered by alpha and version). There's no better way for us to do that, and as such not activating at the appropriate time could lead to require loading something unrelated. This would therefore be introducing a bug into RubyGems.

    The correct way to solve this issue is to make point releases with appropriate dependency sets.

    August 21st, 2010 @ 08:03 PM

  8. Ryan Bigg
    Ryan Bigg
    • Tag cleared.
    • Importance changed from to Low

    Automatic cleanup of spam.

    October 9th, 2010 @ 10:00 PM

  9. David Trasbo
    David Trasbo
    • State changed from new to wontfix

    As for the issue of telling users that the Rails gem is missing, when it might not actually be the case, I committed a fix a while back: http://github.com/rails/rails/commit/d0d10f51d7b2edea94a00291d79cad...

    As for the other issue: That was actually the main reason Bundler was created. It's a fundamental architectural flaw that will definitely not be fixed in 2.3. You have three options:

    1. Use RVM to isolate gems for each of your applications, thus preventing the need of having multiple versions of the same gem.
    2. Use Bundler which, as mentioned, was created to solve this specific problem.
    3. Or: Upgrade to Rails 3, which uses Bundler by default.

    October 10th, 2010 @ 03:10 PM

  10. bingbing