spree/spree · warning

Spree::Dependencies##{legacy}= is deprecated and NO LONGER C

Error message

Spree::Dependencies##{legacy}= is deprecated and NO LONGER CONSULTED by Spree — the override was not applied. Port the class to the #{current} contract and set #{current}= instead. The #{legacy} name is removed in Spree 6.1.

What it means

In 6.0 the service tier seams became workflow seams (Spree::Workflow classes with named steps). A legacy writer such as Spree::Dependencies.cart_add_item_service = 'MyService' warns with this message and STASHES the value in legacy_workflow_overrides - the override is NOT applied to the workflow seam, because a class written against the old service contract is not interchangeable with the workflow the new call sites consume. Legacy readers return the stash (so legacy code calling its own class keeps working), falling back to the workflow class. Affected keys: cart_add_item_service, cart_recalculate_service, cart_merge_strategy, carts_complete_service, carts_upsert_items_service, payments_handle_webhook_service, fulfillment_create_service, order_cancel_service, order_complete_service, shipment_update_service, fulfillment_update_service, gift_card_apply_service, gift_card_remove_service, gift_card_redeem_service. Removed in Spree 6.1.

Source

Thrown at spree/core/lib/spree/core/dependencies.rb:280

        # Spree.<name> resolves through <name>_class, so the rename needs the
        # constantized reader too.
        define_method("#{legacy}_class") do
          Spree::Deprecation.warn(
            "Spree::Dependencies##{legacy} is deprecated and will be removed in Spree 6.1. " \
            "Use #{current} instead."
          )
          send("#{current}_class")
        end
      end

      def legacy_workflow_overrides
        @legacy_workflow_overrides ||= {}
      end

      LEGACY_WORKFLOW_KEYS.merge(LEGACY_SERVICE_KEYS).each do |legacy, current|
        define_method("#{legacy}=") do |value|
          Spree::Deprecation.warn(
            "Spree::Dependencies##{legacy}= is deprecated and NO LONGER CONSULTED by Spree — " \
            "the override was not applied. Port the class to the #{current} contract and " \
            "set #{current}= instead. The #{legacy} name is removed in Spree 6.1."
          )
          legacy_workflow_overrides[legacy] = value
        end

        define_method(legacy) do
          Spree::Deprecation.warn("Spree::Dependencies##{legacy} is deprecated and will be removed in Spree 6.1. Use #{current} instead.")
          legacy_workflow_overrides.fetch(legacy) { send(current) }
        end

        define_method("#{legacy}_class") do
          Spree::Deprecation.warn("Spree::Dependencies##{legacy} is deprecated and will be removed in Spree 6.1. Use #{current} instead.")
          if legacy_workflow_overrides.key?(legacy)
            value = legacy_workflow_overrides[legacy]
            value.is_a?(String) ? value.constantize : value
          else

View on GitHub (pinned to 06bf66a868)

Solutions

  1. Port the custom class to the workflow contract: subclass Spree::Workflow, express the logic as step/external_step, accept the new keyword vocabulary (cart:, items:, fulfillment:, ...)
  2. Set the new seam in the initializer: Spree::Dependencies.cart_add_item_workflow = 'MyApp::Carts::AddItemWorkflow' (or the matching *_workflow key from the warning text)
  3. Delete the legacy assignment once ported - keep it only while other legacy code still reads the old key
  4. Add a spec asserting the workflow seam resolves to your class, so a silently-stashed override can never ship

Example fix

# before
Spree::Dependencies.cart_add_item_service = 'MyApp::Cart::AddItem'  # warned AND ignored

# after
class MyApp::Carts::AddItemWorkflow < Spree::Workflow
  def perform(cart:, variant:, quantity: nil, metadata: {}, options: {})
    super
    step :apply_loyalty_pricing
  end
end
Spree::Dependencies.cart_add_item_workflow = 'MyApp::Carts::AddItemWorkflow'
Defensive patterns

Strategy: validation

Validate before calling

# After boot, prove your override is live on the seam new call sites consume:
expected = 'MyApp::Carts::AddItemWorkflow'
raise 'override stashed, not applied' unless Spree::Dependencies.cart_add_item_workflow_class == expected

Prevention

When it happens

Trigger: Running an initializer that sets any of the fourteen legacy *_service / cart_merge_strategy keys, e.g. Spree::Dependencies.cart_add_item_service = 'MyApp::Cart::AddItem'. The warning fires at boot, and the customized behavior silently stops being consulted by checkout, cart, webhook, fulfillment and gift-card flows.

Common situations: Apps upgraded from Spree 5.x that swapped checkout/cart services (custom add-item validation, custom completion, custom merge) and find the custom logic inactive after the upgrade; extensions installing overrides via generators; the trap is silent - everything still works, just with default behavior.

Related errors


AI-assisted analysis of spree/spree@06bf66a868 (2026-08-21). Data as JSON: /api/errors/1d165f37acce8059. Report an issue: GitHub.