sprockets: RuntimeError - can't add a new key into hash during iteration

Got this backtrace in development mode while using my app… The page crashed instead of rendering. Haven’t managed to reproduce it though. Tried a few times, both with and without clearing the cache first.

RuntimeError - can't add a new key into hash during iteration:
  /Users/bronson/.rubies/ruby-2.2.2/lib/ruby/2.2.0/set.rb:151:in `replace'
  /Users/bronson/.rubies/ruby-2.2.2/lib/ruby/2.2.0/set.rb:347:in `collect!'
  sprockets (3.5.2) lib/sprockets/loader.rb:85:in `asset_from_cache'
  sprockets (3.5.2) lib/sprockets/loader.rb:57:in `block in load'
  sprockets (3.5.2) lib/sprockets/loader.rb:312:in `block in fetch_asset_from_dependency_cache'
  sprockets (3.5.2) lib/sprockets/loader.rb:308:in `fetch_asset_from_dependency_cache'
  sprockets (3.5.2) lib/sprockets/loader.rb:44:in `load'
  sprockets (3.5.2) lib/sprockets/cached_environment.rb:20:in `block in initialize'
  sprockets (3.5.2) lib/sprockets/cached_environment.rb:47:in `load'
  sprockets (3.5.2) lib/sprockets/base.rb:66:in `find_asset'
  sprockets (3.5.2) lib/sprockets/base.rb:92:in `[]'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:342:in `find_asset'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:323:in `digest_path'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:312:in `asset_path'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:90:in `block in resolve_asset_path'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:230:in `block in resolve_asset'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:229:in `resolve_asset'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:89:in `resolve_asset_path'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:79:in `compute_asset_path'
  actionview (5.0.0.beta2) lib/action_view/helpers/asset_url_helper.rb:144:in `asset_path'
  actionview (5.0.0.beta2) lib/action_view/helpers/asset_url_helper.rb:281:in `stylesheet_path'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:161:in `block (2 levels) in stylesheet_link_tag'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:160:in `block in stylesheet_link_tag'
  sprockets-rails (3.0.1) lib/sprockets/rails/helper.rb:157:in `stylesheet_link_tag'
  app/views/layouts/print.html.haml:9:in `_app_views_layouts_print_html_haml__1453697812607104007_70324318851660'
  actionview (5.0.0.beta2) lib/action_view/template.rb:159:in `block in render'
  activesupport (5.0.0.beta2) lib/active_support/notifications.rb:166:in `instrument'
  actionview (5.0.0.beta2) lib/action_view/template.rb:353:in `instrument'
  actionview (5.0.0.beta2) lib/action_view/template.rb:157:in `render'
  actionview (5.0.0.beta2) lib/action_view/renderer/template_renderer.rb:66:in `render_with_layout'
  actionview (5.0.0.beta2) lib/action_view/renderer/template_renderer.rb:52:in `render_template'
  actionview (5.0.0.beta2) lib/action_view/renderer/template_renderer.rb:14:in `render'
  actionview (5.0.0.beta2) lib/action_view/renderer/renderer.rb:42:in `render_template'
  actionview (5.0.0.beta2) lib/action_view/renderer/renderer.rb:23:in `render'
  actionview (5.0.0.beta2) lib/action_view/rendering.rb:103:in `_render_template'
  actionpack (5.0.0.beta2) lib/action_controller/metal/streaming.rb:217:in `_render_template'
  actionview (5.0.0.beta2) lib/action_view/rendering.rb:83:in `render_to_body'
  actionpack (5.0.0.beta2) lib/action_controller/metal/rendering.rb:52:in `render_to_body'
  actionpack (5.0.0.beta2) lib/action_controller/metal/renderers.rb:144:in `render_to_body'
  actionpack (5.0.0.beta2) lib/abstract_controller/rendering.rb:25:in `render'
  actionpack (5.0.0.beta2) lib/action_controller/metal/rendering.rb:36:in `render'
  actionpack (5.0.0.beta2) lib/action_controller/metal/instrumentation.rb:43:in `block (2 levels) in render'
  activesupport (5.0.0.beta2) lib/active_support/core_ext/benchmark.rb:12:in `block in ms'
  /Users/bronson/.rubies/ruby-2.2.2/lib/ruby/2.2.0/benchmark.rb:303:in `realtime'
  activesupport (5.0.0.beta2) lib/active_support/core_ext/benchmark.rb:12:in `ms'
  actionpack (5.0.0.beta2) lib/action_controller/metal/instrumentation.rb:43:in `block in render'
  actionpack (5.0.0.beta2) lib/action_controller/metal/instrumentation.rb:86:in `cleanup_view_runtime'
  activerecord (5.0.0.beta2) lib/active_record/railties/controller_runtime.rb:25:in `cleanup_view_runtime'
  actionpack (5.0.0.beta2) lib/action_controller/metal/instrumentation.rb:42:in `render'
  app/controllers/comparisons_controller.rb:13:in `print'
  actionpack (5.0.0.beta2) lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
  actionpack (5.0.0.beta2) lib/abstract_controller/base.rb:183:in `process_action'
  actionpack (5.0.0.beta2) lib/action_controller/metal/rendering.rb:30:in `process_action'
  actionpack (5.0.0.beta2) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:126:in `call'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:455:in `call'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:101:in `__run_callbacks__'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:750:in `_run_process_action_callbacks'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:90:in `run_callbacks'
  actionpack (5.0.0.beta2) lib/abstract_controller/callbacks.rb:19:in `process_action'
  actionpack (5.0.0.beta2) lib/action_controller/metal/rescue.rb:27:in `process_action'
  actionpack (5.0.0.beta2) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
  activesupport (5.0.0.beta2) lib/active_support/notifications.rb:164:in `block in instrument'
  activesupport (5.0.0.beta2) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
  activesupport (5.0.0.beta2) lib/active_support/notifications.rb:164:in `instrument'
  actionpack (5.0.0.beta2) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
  actionpack (5.0.0.beta2) lib/action_controller/metal/params_wrapper.rb:248:in `process_action'
  activerecord (5.0.0.beta2) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (5.0.0.beta2) lib/abstract_controller/base.rb:128:in `process'
  actionview (5.0.0.beta2) lib/action_view/rendering.rb:30:in `process'
  actionpack (5.0.0.beta2) lib/action_controller/metal.rb:193:in `dispatch'
  actionpack (5.0.0.beta2) lib/action_controller/metal.rb:265:in `dispatch'
  actionpack (5.0.0.beta2) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
  actionpack (5.0.0.beta2) lib/action_dispatch/routing/route_set.rb:32:in `serve'
  actionpack (5.0.0.beta2) lib/action_dispatch/journey/router.rb:42:in `block in serve'
  actionpack (5.0.0.beta2) lib/action_dispatch/journey/router.rb:29:in `serve'
  actionpack (5.0.0.beta2) lib/action_dispatch/routing/route_set.rb:724:in `call'
  actionview (5.0.0.beta2) lib/action_view/digestor.rb:14:in `call'
  rack (2.0.0.alpha) lib/rack/etag.rb:25:in `call'
  rack (2.0.0.alpha) lib/rack/conditional_get.rb:25:in `call'
  rack (2.0.0.alpha) lib/rack/head.rb:12:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/cookies.rb:608:in `call'
  activerecord (5.0.0.beta2) lib/active_record/query_cache.rb:36:in `call'
  activerecord (5.0.0.beta2) lib/active_record/connection_adapters/abstract/connection_pool.rb:963:in `call'
  activerecord (5.0.0.beta2) lib/active_record/migration.rb:558:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:750:in `_run_call_callbacks'
  activesupport (5.0.0.beta2) lib/active_support/callbacks.rb:90:in `run_callbacks'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/reloader.rb:71:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
  better_errors (2.1.1) lib/better_errors/middleware.rb:84:in `protected_app_call'
  better_errors (2.1.1) lib/better_errors/middleware.rb:79:in `better_errors_call'
  better_errors (2.1.1) lib/better_errors/middleware.rb:57:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
  railties (5.0.0.beta2) lib/rails/rack/logger.rb:36:in `call_app'
  railties (5.0.0.beta2) lib/rails/rack/logger.rb:24:in `block in call'
  activesupport (5.0.0.beta2) lib/active_support/tagged_logging.rb:70:in `block in tagged'
  activesupport (5.0.0.beta2) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (5.0.0.beta2) lib/active_support/tagged_logging.rb:70:in `tagged'
  railties (5.0.0.beta2) lib/rails/rack/logger.rb:24:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/request_id.rb:24:in `call'
  rack (2.0.0.alpha) lib/rack/method_override.rb:22:in `call'
  rack (2.0.0.alpha) lib/rack/runtime.rb:22:in `call'
  activesupport (5.0.0.beta2) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/load_interlock.rb:13:in `call'
  actionpack (5.0.0.beta2) lib/action_dispatch/middleware/static.rb:136:in `call'
  rack (2.0.0.alpha) lib/rack/sendfile.rb:111:in `call'
  railties (5.0.0.beta2) lib/rails/engine.rb:522:in `call'
  rack (2.0.0.alpha) lib/rack/handler/webrick.rb:86:in `service'
  /Users/bronson/.rubies/ruby-2.2.2/lib/ruby/2.2.0/webrick/httpserver.rb:138:in `service'
  /Users/bronson/.rubies/ruby-2.2.2/lib/ruby/2.2.0/webrick/httpserver.rb:94:in `run'
  /Users/bronson/.rubies/ruby-2.2.2/lib/ruby/2.2.0/webrick/server.rb:294:in `block in start_thread'

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Comments: 62 (18 by maintainers)

Commits related to this issue

Most upvoted comments

I’m experiencing the same issue in ActionMailer when the view is rendered.

Same here, Rails 5.0.1, Ruby 2.3.3, Sprockets master, i’m saw this one many times. What i can say. Here is no dependency on single or multiple threads. I’m see this error on both server types, webrick, puma, puma single thread. Also my current project is just Rails dummy app with lots of frontend stuff. So yes, Sprockets need time to update cache on changes.

We’re seeing this issue in production running on jruby 1.7.24 (1.9.3p551) with puma 2.15.x. We’re actually encountering it when we use the image_tag helper and it dives down into sprockets to locate an asset (yes, we have the sprockets runtime enabled in production at the moment).

when you said:

Maybe try using some other cache backends and see if that helps? You can try memcache, filestore, memory store.

Do you mean that we should consider configuring rails to use a different cache backend? e.g. config.cache_store = :memory_store? Or is there a sprockets-specific cache backend? I don’t understand exactly where the cache backend fits into this (sorry for my ignorance, I’m still trying to grok the internals of sprockets).

I’d love to throw together an example app for you, but it’s been surprisingly hard to reproduce. I will see what I can do though.

I am experiencing same issue. Ruby 2.7.1 and rails-6. Occurs when traffic increases. Reproduced it using load-testing (i.e made bundle of 5 api calls) and ran it with 50 users on app hosted on EC-2 instance.

+1 ActionView::Template::Error: can’t add a new key into hash during iteration https://app.honeybadger.io/fault/57486/c6617f5edcae8560e3c2e8ccebaf5c5a

+1 for Rails 5.1.2, Ruby 2.4.1, sprockets (3.7.1) and sprockets-rails (3.2.0).

Seeing the same in Rails 5.0.0.1, sprockets 3.7.0, ruby 2.3.1, puma 3.6.0. Dropping puma to 1 thread did fix it.

Of course, now that I try to recreate the error, it’s playing nice so I lost the stack trace, but it was in set.rb, line 153. I’ll post if it reoccurs.

I tried the following patch instead of the one provided by @elia, and it seems to solve both the can't add a new key into hash during iteration and the no implicit conversion of Set into Array bugs.

  module SprocketsSynchronizedLoader
    def self.prepended(klass)
      klass.class_eval do
        class << self
          attr_reader :mutex
        end
        @mutex = Mutex.new
      end
    end

    def asset_from_cache(key)
      self.class.mutex.synchronize do
        super
      end
    end

    Sprockets::CachedEnvironment.prepend self
  end

I’m seeing this occasionally too. Looks like #518 could fix it 😃

@acrolink Yes, as I mentioned it was Turbolinks configuration on my case. *Please refer my comment above…I added the following

'data-turbolinks-track': 'reload'

to my views/layouts/application file.

I have a PR to fix this issue. https://github.com/rails/sprockets/pull/518

I’m still a bit confused about how it happens. Anything that is being mutated is coming from a Marshal.load from the cache

def asset_from_cache(key)
  asset = cache.get(key, true)

AFAIK each marshal “loaded” object is unique

a = [1,2,3]
b = Marshal.load(Marshal.dump(a))
c = Marshal.load(Marshal.dump(a))

puts b == c
# => True

b << 4 #mutating `b` does not mutate `c`

puts b == c
# => False

Are you all still seeing the error sometimes, or did you stop using sprockets 4 beta?