spring icon indicating copy to clipboard operation
spring copied to clipboard

Spring binstub error when requiring class from lib/ in application.rb

Open olivierlacan opened this issue 4 years ago • 2 comments

Given a file in lib/ named thing.rb which required within application.rb like this:

require_relative "boot"

require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

require "thing"

module Rails611LibRequireSpringBug
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.1

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    # config.time_zone = "Central Time (US & Canada)"
    # config.eager_load_paths << Rails.root.join("lib")

    # NOTE: my intent was to use the following code below:
    # config.middleware.use Thing
  end
end

When rails server is launched, I was surprised to see this Spring-related error. I doubt it's truly related to Spring, but I felt like I should at least document this behavior since it may be surprising to some people.

$ rails s
You've tried to invoke Spring when it's already loaded (i.e. the Spring constant is defined).

This is probably because you generated binstubs with Spring 1.0, and you now have a Spring version > 1.0 on your system. To solve this, upgrade your bundle to the latest Spring version and then run `bundle exec spring binstub --all` to regenerate your binstubs. This is a one-time step necessary to upgrade from 1.0 to 1.1.

Here's the backtrace:

/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:326:in `block in load'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:299:in `load_dependency'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:326:in `load'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/binstub.rb:11:in `<main>'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
/Users/olivierlacan/dev/sandbox/rails-6-1-1-lib-require-spring-bug/bin/spring:10:in `block in <top (required)>'
/Users/olivierlacan/dev/sandbox/rails-6-1-1-lib-require-spring-bug/bin/spring:7:in `tap'
/Users/olivierlacan/dev/sandbox/rails-6-1-1-lib-require-spring-bug/bin/spring:7:in `<top (required)>'
bin/rails:2:in `load'
bin/rails:2:in `<main>'

The only way I avoid it is by moving the require call within the Application class definition, which I had to do in the case where Thing is a Rack middleware I wanted to insert. Although I don't have huge qualms about having to do so, I don't remember specific instructions from the Rails Guides warning against requiring (non reloadable) code outside of the Application class definition. But I'll admit I might just be tired.

Here's a reproduction app: https://github.com/olivierlacan/rails-6-1-1-lib-require-spring-bug

I did initially follow the instructions to bundle exec spring binstub --all but I doubt this issue has anything to do with the Spring version since this is a brand new app whose binstubs are Spring 2.1.1 native.

Considering the Stacktrace, this feels more likely to be a Bootsnap bug so I'll gladly move this issue over to that repo if that makes more sense.

olivierlacan avatar Feb 04 '21 05:02 olivierlacan

I tried to repro this, but I couldn't. I get this:

$ rails s
Traceback (most recent call last):
	45: from bin/rails:2:in `<main>'
	44: from bin/rails:2:in `load'
	43: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/bin/spring:7:in `<top (required)>'
	42: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/bin/spring:7:in `tap'
	41: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/bin/spring:10:in `block in <top (required)>'
	40: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
	39: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
	38: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/binstub.rb:11:in `<top (required)>'
	37: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/binstub.rb:11:in `load'
	36: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/bin/spring:49:in `<top (required)>'
	35: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/client.rb:30:in `run'
	34: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/client/command.rb:7:in `call'
	33: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/client/rails.rb:28:in `call'
	32: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/client/rails.rb:28:in `load'
	31: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/bin/rails:5:in `<top (required)>'
	30: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
	29: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
	28: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
	27: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
	26: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
	25: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/commands.rb:18:in `<main>'
	24: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/command.rb:50:in `invoke'
	23: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/command/base.rb:69:in `perform'
	22: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor.rb:392:in `dispatch'
	21: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor/invocation.rb:127:in `invoke_command'
	20: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor/command.rb:27:in `run'
	19: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/commands/server/server_command.rb:135:in `perform'
	18: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/commands/server/server_command.rb:135:in `tap'
	17: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/commands/server/server_command.rb:138:in `block in perform'
	16: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:332:in `require'
	15: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:299:in `load_dependency'
	14: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:332:in `block in require'
	13: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
	12: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
	11: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
	10: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
	 9: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
	 8: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/config/application.rb:9:in `<main>'
	 7: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:332:in `require'
	 6: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:299:in `load_dependency'
	 5: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:332:in `block in require'
	 4: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:44:in `require'
	 3: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
	 2: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/loaded_features_index.rb:89:in `register'
	 1: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require': cannot load such file -- thing (LoadError)

If I manually add lib to the LOAD_PATH using RUBYOPT=-Ilib rails s, then the app boots fine.

deivid-rodriguez avatar Feb 04 '21 19:02 deivid-rodriguez

So @olivierlacan, close it please.

JuPlutonic avatar Mar 28 '21 18:03 JuPlutonic