Rails : RuntimeError - can't modify frozen Array when running rspec in rails
Asked Answered
K

21

62

I recently upgraded to Rails 5.1 from v4.3 and am now getting this error when running tests:

An error occurred while loading 

./spec/controllers/admin/capacity_charges_controller_spec.rb.
Failure/Error: require File.expand_path('../../config/environment', __FILE__)

RuntimeError:
  can't modify frozen Array

I get it for every test file. The line that triggers the error comes from rails_helper. I've checked rails 5.1 sample repos and there's nothing substantially different about our version.

The full stack trace is:

RuntimeError:


can't modify frozen Array
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/actionpack-5.1.0/lib/action_dispatch/middleware/stack.rb:74:in `insert'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/actionpack-5.1.0/lib/action_dispatch/middleware/stack.rb:74:in `insert'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/actionpack-5.1.0/lib/action_dispatch/middleware/stack.rb:81:in `insert_after'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/request_store-1.3.2/lib/request_store/railtie.rb:5:in `block in <class:Railtie>'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/railties-5.1.0/lib/rails/initializable.rb:30:in `instance_exec'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/railties-5.1.0/lib/rails/initializable.rb:30:in `run'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/railties-5.1.0/lib/rails/initializable.rb:59:in `block in run_initializers'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/railties-5.1.0/lib/rails/initializable.rb:58:in `run_initializers'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/railties-5.1.0/lib/rails/application.rb:353:in `initialize!'
# ./config/environment.rb:5:in `<top (required)>'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `require'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `block in require'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:258:in `load_dependency'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `require'
# ./spec/rails_helper.rb:12:in `<top (required)>'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `require'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `block in require'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:258:in `load_dependency'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `require'
# ./spec/controllers/admin/capacity_charges_controller_spec.rb:3:in `<top (required)>'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:286:in `load'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:286:in `block in load'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:258:in `load_dependency'
# /Users/jeremynagel/.rvm/gems/[email protected]_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:286:in `load'
Kraul answered 16/11, 2017 at 2:52 Comment(0)
K
69

Turns out this was caused by test failures higher in the stack trace. It was hard to see what the root cause was because there was so much in the console. If you get this issue, I'd suggest using --fail-fast so you don't get overwhelmed with recurrent error messages. Then check what the first error is.

Kraul answered 17/11, 2017 at 6:30 Comment(8)
pg connection in my case :)Ophiuchus
I had a duplicate factory generator name in my factory_bot spec, which caused thisBickel
I had a file foo/bar.rb which did not define the constant Foo::Bar in my case. This only failed with activated eager loading.Nakitanalani
Yeah, this error is horrible. Every time I mess up renaming a file or renaming a require path somewhere I get this error. And then good luck finding this one-letter typo somewhere in hundreds of my files.Mislay
--fail-fast didn't work, but piping the output into more worked fine. Turns out I had some duplicated traits in my FactoryBot file.Acetophenetidin
For me, the issue was that I was running all my specs. When I ran the spec for a single file, it gave a much more clear error message ( bundle exec rspec spec/models/some_model_spec.rb)Quiroz
This is an alternative to spot the problem rspec --fail-fast | headHumanly
Still an issue, solved by rspec --fail-fast | head. Anyone know why this happens? Can we fix it?Anthracoid
A
13

For me it was a FactoryBot update from version 4 to 5. I didn't see the deprecation warning because I jumped versions:

DEPRECATION WARNING: Static attributes will be removed in FactoryBot 5.0.
Atchison answered 2/4, 2019 at 8:45 Comment(1)
this worked for me as well changing last_name "Lincoln" to last_name { "Lincoln" } in the /spec/factories resolved the frozen array errorStaves
J
12

I did rspec | less to find the first error

Jainism answered 26/3, 2022 at 21:44 Comment(0)
L
9

Check that your Test DB is up to date before anything else.

rake db:test:prepare.

Laskowski answered 11/6, 2019 at 18:20 Comment(0)
U
5

Sometimes this exception is also raised if you have a wrong class name inheritance in your Ruby classes. Remember that controllers, models, etc, are all constants in Ruby.

This is an example off the top-of-my-head of a situation I encountered. Actual syntax may be off, but this was the concept that caused my problem.

module Admin
  class BaseController < ::ApplicationController
    ...
  end
end

# throws error, referencing constant that does not exist.
# Should be < ::Admin::BaseController
class OtherController < ::BaseController
end

Like others, my entire rspec suite would fail with the error can't modify a frozen Array, which isn't a very helpful stacktrace in this instance, per se.

Hope this save someone else from spending hours hunting down everything else!

Upstanding answered 15/1, 2019 at 18:20 Comment(1)
How did you track down the cause of this problem?Debouchment
C
3

I'll post my cause, but first I'll post a troubleshooting path to help you find your cause, as this error can show up for a myriad of reasons.

This is a fairly useless error in most contexts, and the stack trace is impenetrable. I've examined all the gem code in the stack, and none of it points to the actual source of the problem:

# /Users/dh/.gem/gems/actionpack-5.2.3/lib/action_dispatch/middleware/stack.rb:76:in `insert'
# /Users/dh/.gem/gems/actionpack-5.2.3/lib/action_dispatch/middleware/stack.rb:76:in `insert'
# /Users/dh/.gem/gems/actionpack-5.2.3/lib/action_dispatch/middleware/stack.rb:83:in `insert_after'
# /Users/dh/.gem/gems/request_store-1.4.1/lib/request_store/railtie.rb:5:in `block in <class:Railtie>'
# /Users/dh/.gem/gems/railties-5.2.3/lib/rails/initializable.rb:32:in `instance_exec'
# /Users/dh/.gem/gems/railties-5.2.3/lib/rails/initializable.rb:32:in `run'
# /Users/dh/.gem/gems/railties-5.2.3/lib/rails/initializable.rb:61:in `block in run_initializers'
# /Users/dh/.gem/gems/railties-5.2.3/lib/rails/initializable.rb:60:in `run_initializers'
# /Users/dh/.gem/gems/railties-5.2.3/lib/rails/application.rb:361:in `initialize!'
# ./config/environment.rb:5:in `<top (required)>'

To track down why you're getting this error, first comment out (or change back) whatever you did last and see if the problem goes away. If not, restore that line of code, then git stash to hide all your recent changes and run tests.

That will probably fix the issue, and you can git stash pop and start dividing your changes in half until you identify where the problem is.

If git stash does not fix the issue, then you know the problem is either external to your code, or was present in your last commit.

If you know your previous commit tested clean, start looking at your databases, bundle your gems, changes to ENV vars you use, or other environmental factors your app depends on.

If git stash did not fix the problem, and you don't know if your last commit was previously testing clean, start digging back through your commits, either manually or with git bisect. If you can find a commit that started breaking tests, you'll be able to track down the line that is triggering this error.

--

As for my particular issue, it was a typo in a new has_many relationship I added:

  has_many :marijunas, class_name: Drug

Once I narrowed down the change to that line, the fix became obvious:

  has_many :marijunas, class_name: :Drug
Careworn answered 1/5, 2020 at 14:46 Comment(2)
Fun project you're up to! :)Unlive
Can I collab on this project? ;PJuliettajuliette
B
2

When i got the same error with similar stacktrace, it helped me to fix a syntax error in factories.

Bikini answered 15/3, 2019 at 12:54 Comment(0)
Y
2

In case this helps anyone in future, it was database connection issue (Postgresql in my case). Head over to config/database.yml file and supply username: and password: < default is toor>

Add this in the development: group.

Yarn answered 31/7, 2019 at 11:43 Comment(0)
G
2

Suggestion: try loading the app in development after adding config.eager_load = true to your development.rb file, which should give you an actually useful error message pinpointing the problem code.

In my case, a Rails 5.2 app, it was purely a result of upgrading from Ruby 2.4.5 to 2.5.8 which pinpointed the sole issue was unmatched range specifier in char-class in a very long regex that has been working for years.

Giacomo answered 18/10, 2020 at 7:52 Comment(0)
A
2

I think when i had similar problem, it was due to syntax error. Try to run rails db:migrate to show more information on the line where error occur

Anthrax answered 4/3, 2021 at 4:38 Comment(0)
J
2

It was because I forgot to add bullet to the test group in Gemfile, looking at the top of the errors I saw:

NameError:
  uninitialized constant Bullet
Jainism answered 14/3, 2021 at 13:14 Comment(1)
This was my issue as well. Current instructions for bullet only suggest it be added to the "development" group.Blennioid
E
1

In my case recent rails_admin required some addition

RuntimeError: Required middlewares for RailsAdmin are not added
To fix tihs, add

config.middleware.use ActionDispatch::Flash

to config/application.rb.

Then all rspecs became green again.

Epsomite answered 12/9, 2018 at 9:5 Comment(0)
A
1

In my case it was due to a git conflict message (the one like >>>> ... === ... <<<<) that I missed to resolve, so there was a syntax error when Rspec has been trying to load that class.

--fail-fast command line option does not help in this case as the error happens higher in the call stack, but you can see the actual error by just running any single spec file.

Acaleph answered 17/10, 2018 at 9:6 Comment(0)
G
1

I had this same issue when working on an application with Rails 6.

The issue was that when I ran the command rspec I get the error below. The output below is shortened:

An error occurred while loading ./spec/routing/applyportal/school_histories_routing_spec.rb.
Failure/Error: require File.expand_path('../config/environment', __dir__)

FrozenError:
  can't modify frozen Array: ["/home/promisechukwuenyem/Projects/myapp/app/channels", 

Here's how I solved it:

The issue was a result of errors in my code after I did a git pull.

Since I was running in development, I tried dropping my database using:

rails db:drop

Note: This did not drop my database, as the command was interrupted by the error in my code.

And then the actual place where the error was showed up in my terminal which was my config/route.rb file.

I had open my config/route.rb file. And then I found this:

# frozen_string_literal: true

Rails.application.routes.draw do
<<<<<<< HEAD
  resources :courses
=======
  resources :results
>>>>>>> Added result and result upload feature
  resources :books
  resources :schools
end

And then modified it to this:

# frozen_string_literal: true

Rails.application.routes.draw do
  resources :books
  resources :results
  resources :schools
end

That's all.

I hope this helps

Grekin answered 25/3, 2021 at 2:36 Comment(0)
H
1

In my case, it turned out to be an issue with a config.after_initialize block failure, hidden during a rspec run.

However, the error surfaced when I called $ rails c -e test. Hope this helps someone with this being my first post.

Hesse answered 7/2, 2023 at 15:27 Comment(0)
G
0

I tried to update from Rails 3 to Rails 5. I just set config.eager_load option and it helped. Either to false or true. Not nil, please

Goby answered 29/7, 2018 at 13:44 Comment(0)
H
0

My two-cents, as it may help someone else. I had this same issue when upgrading rails 4.2 to 5.0 I saw a thread post somewhere that suggested running one spec-test by itself / at a time. When I did that, I got a different error: superclass must be a Class and pointed me to my new .../models/application_record.rb file, in which I had made a syntax error by omission:

class ApplicationRecord < ActiveRecord                              
  self.abstract_class = true
end

The above is missing ::Base after ActiveRecord -- first line.

class ApplicationRecord < ActiveRecord::Base                                
  self.abstract_class = true
end

Adding that back in fixed all my specs.

Homan answered 21/4, 2020 at 18:35 Comment(0)
S
0

Try setting config.eager_load = true in your environment file. This will load all files in memory during boot & will point out existing syntax errors in first place if any.

Sabrina answered 24/9, 2020 at 14:50 Comment(0)
D
0

I got this error when I removed the gem 'Faker' but left the require 'faker' inside factories.rb

Devries answered 24/8, 2021 at 15:46 Comment(0)
J
-1

In my case, there was an error with zeitwerk. You can get detailed information using the command

bin/rails zeitwerk:check
Julio answered 22/5 at 20:43 Comment(1)
The app is being upgraded to Rails 5.1. In that version Zeitwerk is not an option. The command zeitwerk:check is not available.Danelaw
J
-2

Try to run redis and sidekiq on background. In my case it was one of reasons.

Josiejosler answered 22/1, 2020 at 3:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.