jeznag
jeznag

Reputation: 4723

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

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'

Upvotes: 65

Views: 43349

Answers (21)

tuwilof
tuwilof

Reputation: 587

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

bin/rails zeitwerk:check

Upvotes: 1

David Hempy
David Hempy

Reputation: 6247

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

Upvotes: 3

Des
Des

Reputation: 21

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.

Upvotes: 2

Dorian
Dorian

Reputation: 9085

I did rspec | less to find the first error

Upvotes: 13

jeznag
jeznag

Reputation: 4723

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.

Upvotes: 71

georges
georges

Reputation: 282

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

Upvotes: 0

Promise Preston
Promise Preston

Reputation: 28940

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

Upvotes: 1

Dorian
Dorian

Reputation: 9085

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

Upvotes: 2

john nonso
john nonso

Reputation: 37

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

Upvotes: 2

jpw
jpw

Reputation: 19247

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.

Upvotes: 2

Lubdhak
Lubdhak

Reputation: 116

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.

Upvotes: 0

John Cowan
John Cowan

Reputation: 1674

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.

Upvotes: 0

Ruslan Valeev
Ruslan Valeev

Reputation: 1907

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

Upvotes: -2

Khushwanth
Khushwanth

Reputation: 113

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.

Upvotes: 2

monkeyshoulders
monkeyshoulders

Reputation: 101

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

rake db:test:prepare.

Upvotes: 9

schmijos
schmijos

Reputation: 8695

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.

Upvotes: 13

DonPaulie
DonPaulie

Reputation: 2214

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

Upvotes: 2

Dan L
Dan L

Reputation: 4439

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!

Upvotes: 5

trushkevich
trushkevich

Reputation: 2677

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.

Upvotes: 1

Kiryl Plyashkevich
Kiryl Plyashkevich

Reputation: 2277

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.

Upvotes: 1

Orel Sokolov
Orel Sokolov

Reputation: 21

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

Upvotes: 0

Related Questions