rails: intermittent "uninitialized constant ActiveStorage::Attached (NameError)" errors on Rails 6.1.6.1

Steps to reproduce

Unfortunately it is very random and I have not figured out how to reproduce it. It happens when starting the environment. My guess is it’s related to zeitwerk as we recently upgrades to Rails 6.x

irb(main):001:0> Rails.application.config.autoloader
=> :zeitwerk
irb(main):002:0> Rails.application.config.eager_load
=> true

The missing constant we’ve seen the most is ActiveStorage::Attached. Our application code does not reference that class directly, but does use ActiveStorage.

Here is the stack trace.

/home/my_app/vendor/bundle/ruby/2.7.0/gems/activestorage-6.1.6.1/lib/active_storage/attached.rb:8:in `<module:ActiveStorage>': uninitialized constant ActiveStorage::Attached (NameError)

	from /home/my_app/vendor/bundle/ruby/2.7.0/gems/activestorage-6.1.6.1/lib/active_storage/attached.rb:5:in `<main>'
	from /home/my_app/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.12.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
	from /home/my_app/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.12.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
	from /home/my_app/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.6.0/lib/zeitwerk/kernel.rb:35:in `require'
	from /home/my_app/vendor/bundle/ruby/2.7.0/gems/activestorage-6.1.6.1/lib/active_storage/engine.rb:118:in `block in <class:Engine>'
	from /home/my_app/vendor/bundle/ruby/2.7.0/gems/railties-6.1.6.1/lib/rails/initializable.rb:32:in `instance_exec'
	from /home/my_app/vendor/bundle/ruby/2.7.0/gems/railties-6.1.6.1/lib/rails/initializable.rb:32:in `run'

Expected behavior

Rails application should start

Actual behavior

Roughly 2% of the time, the application fails to start with a missing constant related to a rails class. When looking at it today, it’s been ActiveStorage::Attached

System configuration

Rails version: 6.1.6.1

Ruby version: 2.7.6p219

Zeitwerk version: 2.6.0

Bootsnap version: 1.12.0

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 18 (5 by maintainers)

Most upvoted comments

@maximevaillancourt We do use both of those gems. I’ll catch up on your investigation. Thanks for following up!

Interesting, thank you for sharing.

For the record: I’ve been seeing this issue with non-Rails constants too, such as constants from external gems that we use within our Rails app, and some of our own internal constants as well (e.g. a plain old Ruby class).

Here are the gem-related constants we see missing every once in a while (with NameError: uninitialized constant), even though we don’t explicitly refer to those in our application code:

  • ActiveStorage::Attached
  • ActiveStorage::Attached::Changes::CreateOne
  • ActionView::TemplatePath
  • Formtastic::Helpers::FormHelper
  • RailsSemanticLogger::ActiveJob::LogSubscriber
  • ViewComponent::Compiler
  • ViewComponent::TestHelpers

We’ve tried adding explicit require calls for these, but no dice, still seeing uninitialized constant exceptions pop up every now and then. I’ve tried removing/disabling pry/byebug based on a previous comment in this thread, but that didn’t help either.

These seem to happen regardless of eager_load being true or false.

Disabling Bootsnap entirely (with DISABLE_BOOTSNAP=1) turns these exceptions into LoadError: cannot load such file, which is different, but seemingly related.

I saw that race conditions in the way Ruby autoloads code were fixed in Ruby 3.2.0 (see Ruby bug tracker issue and Ruby 3.2.0 release notes), but apparently this bug happened on Ruby 2.7 too (as stated in the issue description).

This Ruby PR is interesting though: https://github.com/ruby/ruby/pull/5788

Our current setup, in case it helps anyone: Rails 7.0.4 (Zeitwerk 2.6.6), Ruby 3.2.0, and Bootsnap 1.15.0.

I haven’t figured out how to make it happen. It hasn’t happened since I opened the issue. There are no model references in the initializers. If I figure out how to make it happen consistently, I’ll update this issue.