spree/spree · warning

Spree::StockLocation#stock_item is deprecated and will be re

Error message

Spree::StockLocation#stock_item is deprecated and will be removed in Spree 6.1. Use #stock_level instead.

What it means

Spree 6.0 renamed the StockItem model to StockLevel (typed-stock-movements rework: table prefixes si_→sl_, endpoints /stock_levels). StockLocation#stock_item is a one-release bridge that delegates to #stock_level and emits this warning on every call; it is deleted in 6.1, after which calls raise NoMethodError.

Source

Thrown at spree/core/app/models/spree/stock_location.rb:88

    #
    # @return [StockLevel] Corresponding StockLevel for the StockLocation's variant.
    def stock_level(variant_id)
      stock_levels.where(variant_id: variant_id).order(:id).first
    end

    def stocks?(variant)
      stock_levels.exists?(variant: variant)
    end

    # @deprecated Use {#stock_levels}; removed in 6.1.
    def stock_items
      Spree::Deprecation.warn('Spree::StockLocation#stock_items is deprecated and will be removed in Spree 6.1. Use #stock_levels instead.')
      stock_levels
    end

    # @deprecated Use {#stock_level}; removed in 6.1.
    def stock_item(variant_id)
      Spree::Deprecation.warn('Spree::StockLocation#stock_item is deprecated and will be removed in Spree 6.1. Use #stock_level instead.')
      stock_level(variant_id)
    end

    # @deprecated Use {#set_up_stock_level}; removed in 6.1.
    def set_up_stock_item(variant)
      Spree::Deprecation.warn('Spree::StockLocation#set_up_stock_item is deprecated and will be removed in Spree 6.1. Use #set_up_stock_level instead.')
      set_up_stock_level(variant)
    end

    # @deprecated Use {#stock_level_or_create}; removed in 6.1.
    def stock_item_or_create(variant_or_variant_id)
      Spree::Deprecation.warn('Spree::StockLocation#stock_item_or_create is deprecated and will be removed in Spree 6.1. Use #stock_level_or_create instead.')
      stock_level_or_create(variant_or_variant_id)
    end

    # Attempts to look up StockLevel for the variant, and creates one if not found.
    #
    # @param variant Variant instance or Variant ID

View on GitHub (pinned to 06bf66a868)

Solutions

  1. Replace the call with stock_location.stock_level(variant_id) — identical argument shape (variant or variant id) and identical return type (Spree::StockLevel).
  2. If the call is inside a gem you cannot edit, upgrade that gem to its Spree 6-compatible version, or fork and change that one line.
  3. For code that must run on both 5.x and 6.0, bridge with location.respond_to?(:stock_level) and prefer the new name.
  4. As a stopgap wrap the call in Spree::Deprecation.silence { ... } while you schedule the rename — never leave this in place past the 6.1 upgrade.

Example fix

// before
stock_item = stock_location.stock_item(variant.id)

// after
stock_level = stock_location.stock_level(variant.id)
Defensive patterns

Strategy: fallback

Validate before calling

if stock_location.respond_to?(:stock_level)
  level = stock_location.stock_level(variant.id)
else
  level = stock_location.stock_item(variant.id)
end

Type guard

def spree_stock_level_api?(stock_location)
  stock_location.respond_to?(:stock_level)
end

Prevention

When it happens

Trigger: Calling stock_location.stock_item(variant_id) — e.g. a stock-sync rake task, extension code, serializer or console snippet written against Spree 5.x that looked up the per-location stock row before reading/writing count_on_hand.

Common situations: An extension or copied app code written for Spree <= 5.6 running on a 6.0 app; CSV import jobs that ensured a stock item existed per location; a third-party gem that has not shipped a Spree 6-compatible release yet.

Related errors


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