Yet another "A copy of XXX has been removed from the module tree but is still active!" - can we add an example?

Hi,

It’s been a few hours and I am still fighting with a “A copy of XXX has been removed from the module tree but is still active!”.

My goal with this post is to discuss shouldn’t there be more information about this particular error on the rails guides. Sorry if there already is, but I could not find it.

The error is commonly occurring (a few searches): https://discuss.rubyonrails.org/search?q=has%20been%20removed%20from%20the%20module%20tree%20but%20is%20still%20active! Posts containing 'has been removed from the module tree but is still active' - Stack Overflow

There are answers from 2009, there are answers with Dependencies before it was in ActiveSupport, there are some answers that are plain wrong, there are dozens of blogs posts, but I could not find an explanation and example on the rails guides.

People are suggesting things like (to list a few)

config.paths.add
config.autoload_paths 
config.eager_load_paths 
Zeitwerk::Loader.eager_load_all
config.eager_load_namespaces
require_dependency
Rails.application.eager_load!
Rails.configuration.eager_load_namespaces.each(&:eager_load!)
Dependencies.load_once_paths
unloadable

I’ve been through:

https://apidock.com/rails/ActiveSupport/Dependencies/Loadable/unloadable and through many more, but I cant find an example that would lead to this error and explanation on why it occurs and how to fix it.

I personally kind of understand the error and why it is happening, yet I still can’t find a way to resolve it in my case. My specific case even involves spring and the class in question comes from an Engine and it only occurs after a spec has failed. So it makes things more difficult.

My recommendation is that we should build an ‘example’ of when and how such an error could occur in an real life scenario. Looking at activesupport-6.0.3.1/lib/active_support/dependencies.rb:529 there are more cases where similar errors could occur.

I would love to volunteer, but I do not think I understand the error well enough (I still can not resolve it in my case).

I would also not argue that there should be a more understandable explanation for every ‘error’ there is and how to approach it, but following the May of WTF posts last month, there could be an added value if more examples and explanations are added about this particular error.

1 Like

My general impression is that I only run into that error when trying to access previously loaded variables after calling reload! in the console. Quite rare otherwise.

2 Likes

Hey there!

This is my first time posting on the Rails discussion forum, so forgive me if my formatting or response is out-of-the-norm.

Would you be able to post an example of what your codebase looks like and/or where you think the error is occurring? I have battled this as well and taken the deep dive to figure it out. I would love to take a look at your instance and see if I could help at all!

Thanks. It would be difficult to reproduce the exact setup that I had in this platform. There was a gem called wisper involved. There was a config/initializers/wisper.rb that as adding a global wisper listener. This listener was called with a broadcast method in an after_callback.

This was a nice way of decoupling some logic years ago. The class that was actually removed from the module tree was the wisper listener.

When you are making changes in the user.rb code, it reloads, but it does not call config/initializers/wisper.rb again, and there is the old listener the is still registered. Now, why does this matter I don’t know, but I had to explicitly add ::MyWisperListener at the top of the user.rb.

But then things got even more ugly so I just remove wisper on this particular instance. It was a bad idea for this case that was still staying as legacy.

Ahh that is interesting. i love those kinds of issues, I always learn really cool things about Rails. I may try and repro this locally if I have time!

@kmitov, we hit this recently and it is basically what is described here: Autoloading and Reloading Constants (Zeitwerk Mode) — Ruby on Rails Guides

In our case we were storing an AR model in threadsafe_storage that cause the issue. The solution we used was to do a new lookup for the object when in development environment (as test/prod don’t do code reloading it’s not needed there).

A simple example, instead of:

def common_object
   $thing # global object, purely for demonstration purposes
end

We use:

def common_object
  thing = $thing
  thing = Thing.find(thing.id) if Rails.env.development? # get a new instance if in a code-reloading environment
  thing
end

That’s good. One more example added here for people that hit this error.

On a side note and just qurios - do you feel comfortable with

thing = Thing.find(thing.id) if Rails.env.development?

in production code?