Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't modify frozen Array error when running rspec in Rails 5.1 #534

Closed
maxim opened this issue Mar 10, 2019 · 5 comments
Closed

Can't modify frozen Array error when running rspec in Rails 5.1 #534

maxim opened this issue Mar 10, 2019 · 5 comments
Labels
feature request Request for a new feature released This feature/bug fix has been released

Comments

@maxim
Copy link
Contributor

maxim commented Mar 10, 2019

Description

Trying to run rspec after updating rails from 5.0 to 5.1 causes "can't modify frozen Array" error that (upon some research) bugsnag causes when trying to initialize. Seems like it's injecting a middleware after the stack is already frozen.

Issue

In a simple rails app I have this config/initializers/bugsnag.rb

Bugsnag.configure do |config|
  config.api_key = '[api-key]'
  config.notify_release_stages = %w[production staging]
  config.release_stage = ENV['BUGSNAG_ENV'] || Rails.env
end

After updating Rails from 5.0 => 5.1, trying to run rspec causes this error on every spec.

Failure/Error: require File.expand_path('../config/environment', __dir__)

FrozenError:
  can't modify frozen Array
# ~/.asdf/installs/ruby/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.1.6.1/lib/action_dispatch/middleware/stack.rb:95:in `push'
# ~/.asdf/installs/ruby/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.1.6.1/lib/action_dispatch/middleware/stack.rb:95:in `use'
# ~/.asdf/installs/ruby/2.5.3/lib/ruby/gems/2.5.0/gems/bugsnag-6.11.1/lib/bugsnag/integrations/railtie.rb:67:in `rescue in block in <class:Railtie>'
# ~/.asdf/installs/ruby/2.5.3/lib/ruby/gems/2.5.0/gems/bugsnag-6.11.1/lib/bugsnag/integrations/railtie.rb:64:in `block in <class:Railtie>'
# ~/.asdf/installs/ruby/2.5.3/lib/ruby/gems/2.5.0/gems/railties-5.1.6.1/lib/rails/initializable.rb:30:in `instance_exec'
# ~/.asdf/installs/ruby/2.5.3/lib/ruby/gems/2.5.0/gems/railties-5.1.6.1/lib/rails/initializable.rb:30:in `run'
# ~/.asdf/installs/ruby/2.5.3/lib/ruby/gems/2.5.0/gems/railties-5.1.6.1/lib/rails/initializable.rb:59:in `block in run_initializers'
# …snip…

I read through PRs #419, #444, as well issues #403 and #391, and saw the "doc" for the fix at the bottom of this page, and I'm still unclear what I need to do.

I tried setting BUGSNAG_DISABLE_AUTOCONFIGURE=true in my local .env (and moving dotenv gem to the top of Gemfile). I also tried running rspec like this: BUGSNAG_DISABLE_AUTOCONFIGURE=true rspec. it didn't help.

I'm still not sure, and the doc could use a lot of improvement, since it currently seems to be targeting bugsnag developers, and even after quite a number of years doing this, I couldn't understand what it's telling me to do. I'm quoting here:

By default all Ruby framework integrations Bugsnag provides

I don't know what integrations bugsnag provides, up to today bugsnag didn't ask me to configure any integrations. I guess it integrates with rails and sidekiq, is sidekiq a framework?

will be initialized when the notifier is loaded.

What does it mean for "framework integrations" to "initialize"? What is "the notifier"? What does it mean for it to be loaded?

This behaviour can be disabled by setting the environment variable BUGSNAG_DISABLE_AUTOCONFIGURE to true inside of your application.

Why would I not want "framework integrations to be initialized when notifier is loaded"?

Integrations can then be required as necessary using: Bugsnag.load_integration(:sidekiq)

What does it mean to load integration? Am I supposed to put this in initializers? Am I supposed add conditions for "when sidekiq is loading, load sidekiq integration"? Where do I load rails integration? Do I have other integrations I need to be loading? I'm not sure, it's a big app, and I didn't write the entire thing myself. Bugsnag didn't need me to do this before.

Any help much appreciated.

Environment

Library versions:

  * bugsnag (6.11.1)
  * dotenv-rails (2.7.1)
  * rails (5.1.6.1)
  * rspec-rails (3.8.2)
  * sidekiq (5.0.5)
@maxim
Copy link
Contributor Author

maxim commented Mar 10, 2019

I couldn't move bugsnag gem into staging, production groups in Gemfile because this codebase often calls Bugsnag directly.

@maxim
Copy link
Contributor Author

maxim commented Mar 10, 2019

Next morning took another stab at it, and found that as this answer suggested, the "frozen array" error was indeed a red herring. Bugsnag just happens to be at the wrong place at the wrong time, since it seems that the first spec error causes the middleware stack to freeze (or something like that), and bugsnag is the first to try inject something after that happens, which then shows up as an error on every other spec. In my case the first error was also very cryptic and seemingly unrelated, which is why I didn't look harder into it.

However, perhaps this issue could be more about bugsnag helping stop people from going down this rabbit hole. I'm sure there will be more people updating their Rails and running into stuff like this. They might then see this doc and assume bugsnag is acknowledging this issue.

People finding this issue: be sure to listen to this advice and really dig into that first error no matter how unrelated it might appear.

@snmaynard
Copy link
Contributor

Glad you got to the bottom of the issue. What would your recommendation be in this case? We could rescue the error that propagates from https://github.com/bugsnag/bugsnag-ruby/blob/master/lib/bugsnag/integrations/railtie.rb#L67 and wrap that exception with a potentially slightly more helpful exception that points people in the right direction?

@maxim
Copy link
Contributor Author

maxim commented Mar 14, 2019

I think that could be a welcome addition! 👍 I would also recommend rephrasing the "Custom middleware loading" doc with the following goals:

  • Use the title to indicate the problem the doc is solving (e.g. Fixing load order issues with custom middleware) so that it's clear that it's for a specific non-standard use case.
  • Illustrate the problem and the solution with a specific example. Made up is ok, but I suggest mentioning that this shouldn't ever be a problem in Rails, and showing an example of what can cause the problem.
  • Avoid words like "initialize" and "notifier" that have vague/unclear meanings. E.g. it could say something along the lines of "If you mount the middleware after Bugsnag is already required, then the middleware errors won't be caught. It's best to only require Bugsnag after everything else has loaded. If in your case that's impossible, you can use the ENV var […] The downside is that it would disable Bugsnag's ability to automatically hook into various libraries, and you would have to do that manually like this: code snippet". (This is based on how I interpreted what that paragraph says, but I'm not sure if I understood it correctly).

@phillipsam phillipsam added backlog We hope to fix this feature/bug in the future feature request Request for a new feature labels Sep 25, 2019
@bugsnagbot bugsnagbot added scheduled Work is starting on this feature/bug and removed backlog We hope to fix this feature/bug in the future labels Jul 7, 2020
imjoehaines added a commit that referenced this issue Jul 23, 2020
This should never happen in normal operation, but is possible when
running RSpec tests

See thoughtbot/factory_bot_rails#303 (comment)
and #534

Essentially this happens:
1. RSpec boots Rails
2. Rails boot process errors
3. Rails freezes middleware
4. RSpec moves on to the next test file
5. Bugsnag tries to add middleware but fails because it's frozen
6. The stacktrace blames Bugsnag for this test failure
7. goto 4

Supressing this error doesn't solve the problem as it's likely another
frozen error will happen in some other library/component, but we want
to avoid people thinking this is caused by Bugsnag. The stacktrace
does point out the actual problem, but only in the very first error,
which can get buried under the frozen errors that happen for each
test file
imjoehaines added a commit that referenced this issue Jul 23, 2020
This should never happen in normal operation, but is possible when
running RSpec tests

See thoughtbot/factory_bot_rails#303 (comment)
and #534

Essentially this happens:
1. RSpec boots Rails
2. Rails boot process errors
3. Rails freezes middleware
4. RSpec moves on to the next test file
5. Bugsnag tries to add middleware but fails because it's frozen
6. The stacktrace blames Bugsnag for this test failure
7. goto 4

Supressing this error doesn't solve the problem as it's likely another
frozen error will happen in some other library/component, but we want
to avoid people thinking this is caused by Bugsnag. The stacktrace
does point out the actual problem, but only in the very first error,
which can get buried under the frozen errors that happen for each
test file
imjoehaines added a commit that referenced this issue Jul 23, 2020
This should never happen in normal operation, but is possible when
running RSpec tests

See thoughtbot/factory_bot_rails#303 (comment)
and #534

Essentially this happens:
1. RSpec boots Rails
2. Rails boot process errors
3. Rails freezes middleware
4. RSpec moves on to the next test file
5. Bugsnag tries to add middleware but fails because it's frozen
6. The stacktrace blames Bugsnag for this test failure
7. goto 4

Supressing this error doesn't solve the problem as it's likely another
frozen error will happen in some other library/component, but we want
to avoid people thinking this is caused by Bugsnag. The stacktrace
does point out the actual problem, but only in the very first error,
which can get buried under the frozen errors that happen for each
test file
imjoehaines added a commit that referenced this issue Jul 27, 2020
This should never happen in normal operation, but is possible when
running RSpec tests

See thoughtbot/factory_bot_rails#303 (comment)
and #534

Essentially this happens:
1. RSpec boots Rails
2. Rails boot process errors
3. Rails freezes middleware
4. RSpec moves on to the next test file
5. Bugsnag tries to add middleware but fails because it's frozen
6. The stacktrace blames Bugsnag for this test failure
7. goto 4

Supressing this error doesn't solve the problem as it's likely another
frozen error will happen in some other library/component, but we want
to avoid people thinking this is caused by Bugsnag. The stacktrace
does point out the actual problem, but only in the very first error,
which can get buried under the frozen errors that happen for each
test file
@phillipsam
Copy link

We have added an update in v6.16.0 to improve the behaviour here.

@phillipsam phillipsam added released This feature/bug fix has been released and removed scheduled Work is starting on this feature/bug labels Aug 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Request for a new feature released This feature/bug fix has been released
Projects
None yet
Development

No branches or pull requests

4 participants