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)
@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 seeinguninitialized 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
beingtrue
orfalse
.Disabling Bootsnap entirely (with
DISABLE_BOOTSNAP=1
) turns these exceptions intoLoadError: 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.