Skip to content

Bug: NoMethodError when calling memoized methods within Rails.cache.fetch #373

@pioz

Description

@pioz

I'm encountering the following error when running my test suite:

Run options: --seed 36906

# Running:

E

Error:
CreateFutureOrdersTest#test_create_future_order:
NoMethodError: undefined method `[]' for nil
    memo_wise (1.10.0) lib/memo_wise.rb:205:in `min_shipping_method_cost'
    app/models/shipping_method.rb:157:in `calculated_price'
    app/services/available_shipping_methods_service.rb:165:in `block in filter_by_weight'
    app/services/available_shipping_methods_service.rb:113:in `reject'
    app/services/available_shipping_methods_service.rb:113:in `reject'
    app/services/available_shipping_methods_service.rb:165:in `filter_by_weight'
    app/services/available_shipping_methods_service.rb:101:in `fetch_shipping_methods_for_subcart'
    app/services/available_shipping_methods_service.rb:92:in `cached_shipping_methods_for_subcart'
    app/services/available_shipping_methods_service.rb:41:in `shipping_method'
    memo_wise (1.10.0) lib/memo_wise.rb:240:in `block in shipping_method'
    memo_wise (1.10.0) lib/memo_wise.rb:239:in `fetch'
    memo_wise (1.10.0) lib/memo_wise.rb:239:in `shipping_method'
    app/controllers/concerns/cart_purchase_request_concern.rb:197:in `block in force_valid_shipping_methods'
    activerecord (7.2.2.1) lib/active_record/relation/delegation.rb:98:in `each'
    activerecord (7.2.2.1) lib/active_record/relation/delegation.rb:98:in `each'
    app/controllers/concerns/cart_purchase_request_concern.rb:194:in `force_valid_shipping_methods'
    app/controllers/concerns/cart_purchase_request_concern.rb:154:in `set_cart_and_normalize'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:362:in `block in make_lambda'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:179:in `block in call'
    actionpack (7.2.2.1) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:180:in `call'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:559:in `block in invoke_before'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:559:in `each'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:559:in `invoke_before'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:119:in `block in run_callbacks'
    react-rails (2.6.2) lib/react/rails/controller_lifecycle.rb:31:in `use_react_component_helper'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:130:in `block in run_callbacks'
    actiontext (7.2.2.1) lib/action_text/rendering.rb:25:in `with_renderer'
    actiontext (7.2.2.1) lib/action_text/engine.rb:71:in `block (4 levels) in <class:Engine>'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:130:in `instance_exec'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:130:in `block in run_callbacks'
    sentry-rails (5.22.1) lib/sentry/rails/controller_transaction.rb:34:in `block in sentry_around_action'
    sentry-ruby (5.22.1) lib/sentry/hub.rb:108:in `with_child_span'
    sentry-ruby (5.22.1) lib/sentry-ruby.rb:503:in `with_child_span'
    sentry-rails (5.22.1) lib/sentry/rails/controller_transaction.rb:18:in `sentry_around_action'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:130:in `block in run_callbacks'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:141:in `run_callbacks'
    actionpack (7.2.2.1) lib/abstract_controller/callbacks.rb:260:in `process_action'
    actionpack (7.2.2.1) lib/action_controller/metal/rescue.rb:27:in `process_action'
    actionpack (7.2.2.1) lib/action_controller/metal/instrumentation.rb:77:in `block in process_action'
    activesupport (7.2.2.1) lib/active_support/notifications.rb:210:in `block in instrument'
    activesupport (7.2.2.1) lib/active_support/notifications/instrumenter.rb:58:in `instrument'
    activesupport (7.2.2.1) lib/active_support/notifications.rb:210:in `instrument'
    actionpack (7.2.2.1) lib/action_controller/metal/instrumentation.rb:76:in `process_action'
    actionpack (7.2.2.1) lib/action_controller/metal/params_wrapper.rb:259:in `process_action'
    activerecord (7.2.2.1) lib/active_record/railties/controller_runtime.rb:39:in `process_action'
    actionpack (7.2.2.1) lib/abstract_controller/base.rb:163:in `process'
    actionview (7.2.2.1) lib/action_view/rendering.rb:40:in `process'
    actionpack (7.2.2.1) lib/action_controller/metal.rb:252:in `dispatch'
    actionpack (7.2.2.1) lib/action_controller/metal.rb:335:in `dispatch'
    actionpack (7.2.2.1) lib/action_dispatch/routing/route_set.rb:67:in `dispatch'
    actionpack (7.2.2.1) lib/action_dispatch/routing/route_set.rb:50:in `serve'
    actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:53:in `block in serve'
    actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:133:in `block in find_routes'
    actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:126:in `each'
    actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:126:in `find_routes'
    actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:34:in `serve'
    actionpack (7.2.2.1) lib/action_dispatch/routing/route_set.rb:896:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/static.rb:27:in `call'
    omniauth (1.9.2) lib/omniauth/strategy.rb:420:in `call_app!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:274:in `mock_call!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:186:in `call!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
    omniauth (1.9.2) lib/omniauth/strategy.rb:420:in `call_app!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:274:in `mock_call!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:186:in `call!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
    omniauth (1.9.2) lib/omniauth/strategy.rb:420:in `call_app!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:274:in `mock_call!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:186:in `call!'
    omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
    rack_session_access (0.2.0) lib/rack_session_access/middleware.rb:33:in `call'
    lib/rack/json_logger_middleware.rb:11:in `call'
    lib/rack/subdomain_frontend_bad_request_middleware.rb:9:in `call'
    remotipart (1.4.4) lib/remotipart/middleware.rb:32:in `call'
    exception_notification (4.5.0) lib/exception_notification/rack.rb:49:in `call'
    warden (1.2.9) lib/warden/manager.rb:36:in `block in call'
    warden (1.2.9) lib/warden/manager.rb:34:in `catch'
    warden (1.2.9) lib/warden/manager.rb:34:in `call'
    rack (2.2.10) lib/rack/tempfile_reaper.rb:15:in `call'
    rack (2.2.10) lib/rack/etag.rb:27:in `call'
    rack (2.2.10) lib/rack/conditional_get.rb:40:in `call'
    rack (2.2.10) lib/rack/head.rb:12:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/http/content_security_policy.rb:38:in `call'
    rack (2.2.10) lib/rack/session/abstract/id.rb:266:in `context'
    rack (2.2.10) lib/rack/session/abstract/id.rb:260:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/cookies.rb:704:in `call'
    lib/rack/cookie_overflow_middleware.rb:9:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/callbacks.rb:31:in `block in call'
    activesupport (7.2.2.1) lib/active_support/callbacks.rb:101:in `run_callbacks'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/callbacks.rb:30:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/actionable_exceptions.rb:18:in `call'
    sentry-rails (5.22.1) lib/sentry/rails/rescued_exception_interceptor.rb:14:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:31:in `call'
    sentry-ruby (5.22.1) lib/sentry/rack/capture_exceptions.rb:30:in `block (2 levels) in call'
    sentry-ruby (5.22.1) lib/sentry/hub.rb:266:in `with_session_tracking'
    sentry-ruby (5.22.1) lib/sentry-ruby.rb:416:in `with_session_tracking'
    sentry-ruby (5.22.1) lib/sentry/rack/capture_exceptions.rb:21:in `block in call'
    sentry-ruby (5.22.1) lib/sentry/hub.rb:59:in `with_scope'
    sentry-ruby (5.22.1) lib/sentry-ruby.rb:396:in `with_scope'
    sentry-ruby (5.22.1) lib/sentry/rack/capture_exceptions.rb:20:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/show_exceptions.rb:32:in `call'
    railties (7.2.2.1) lib/rails/rack/logger.rb:41:in `call_app'
    railties (7.2.2.1) lib/rails/rack/logger.rb:29:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/remote_ip.rb:96:in `call'
    request_store (1.7.0) lib/request_store/middleware.rb:19:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/request_id.rb:33:in `call'
    rack (2.2.10) lib/rack/method_override.rb:24:in `call'
    rack (2.2.10) lib/rack/runtime.rb:22:in `call'
    activesupport (7.2.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/executor.rb:16:in `call'
    actionpack (7.2.2.1) lib/action_dispatch/middleware/static.rb:27:in `call'
    rack (2.2.10) lib/rack/sendfile.rb:110:in `call'
    rack (2.2.10) lib/rack/deflater.rb:44:in `call'
    lib/rack/bad_parameters_handler_middleware.rb:11:in `call'
    lib/rack/utf8_sanitizer_middleware.rb:19:in `call'
    lib/rack/cloudflare_middleware.rb:18:in `call'
    lib/rack/force_format_json_middleware.rb:8:in `call'
    rack-cors (2.0.2) lib/rack/cors.rb:102:in `call'
    railties (7.2.2.1) lib/rails/engine.rb:535:in `call'
    rack-test (2.2.0) lib/rack/test.rb:360:in `process_request'
    rack-test (2.2.0) lib/rack/test.rb:153:in `request'
    actionpack (7.2.2.1) lib/action_dispatch/testing/integration.rb:287:in `process'
    actionpack (7.2.2.1) lib/action_dispatch/testing/integration.rb:25:in `post'
    actionpack (7.2.2.1) lib/action_dispatch/testing/integration.rb:378:in `post'
    test/integration/create_future_orders_test.rb:95:in `block in <class:CreateFutureOrdersTest>'
    minitest (5.25.4) lib/minitest/test.rb:94:in `block (2 levels) in run'
    minitest (5.25.4) lib/minitest/test.rb:190:in `capture_exceptions'
    minitest (5.25.4) lib/minitest/test.rb:89:in `block in run'
    minitest (5.25.4) lib/minitest.rb:368:in `time_it'
    minitest (5.25.4) lib/minitest/test.rb:88:in `run'
    activesupport (7.2.2.1) lib/active_support/executor/test_helper.rb:5:in `block in run'
    activesupport (7.2.2.1) lib/active_support/execution_wrapper.rb:104:in `perform'
    activesupport (7.2.2.1) lib/active_support/executor/test_helper.rb:5:in `run'
    minitest (5.25.4) lib/minitest.rb:1208:in `run_one_method'
    minitest (5.25.4) lib/minitest.rb:447:in `run_one_method'
    minitest (5.25.4) lib/minitest.rb:434:in `block (2 levels) in run'
    minitest (5.25.4) lib/minitest.rb:430:in `each'
    minitest (5.25.4) lib/minitest.rb:430:in `block in run'
    minitest (5.25.4) lib/minitest.rb:472:in `on_signal'
    minitest (5.25.4) lib/minitest.rb:459:in `with_info_handler'
    minitest (5.25.4) lib/minitest.rb:429:in `run'
    railties (7.2.2.1) lib/rails/test_unit/line_filtering.rb:10:in `run'
    minitest (5.25.4) lib/minitest.rb:332:in `block in __run'
    minitest (5.25.4) lib/minitest.rb:332:in `map'
    minitest (5.25.4) lib/minitest.rb:332:in `__run'
    minitest (5.25.4) lib/minitest.rb:288:in `run'
    minitest (5.25.4) lib/minitest.rb:86:in `block in autorun'


bin/rails test test/integration/create_future_orders_test.rb:66

This error occurs when I call memoized methods inside a Rails.cache.fetch block, like this:

Rails.cache.fetch(key, expires_in: 2.hours) do
  # Call memoized methods here
end

If I comment out the Rails.cache.fetch block and call the same memoized methods directly, the test passes without any errors.

Unfortunately, despite my efforts, I have been unable to isolate the issue into a reproducible script. The issue appears tied to the specific interactions in my application. I have tried various approaches to debug and isolate the issue but have been unable to reproduce it outside the context of my application. I suspect the interaction between Rails.cache and MemoWise might be causing this unexpected behavior in some edge cases.

Let me know if you need additional information or if there are specific debugging steps you'd like me to take. Thanks for your help!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions