medusajs/medusa · error · MedusaError

"items" should be present as an array in the context to comp

Error message

"items" should be present as an array in the context to compute actions

What it means

computeActions for a buy-get promotion requires the computation context to contain an 'items' array (ComputeActionItemLine[]). isValidPromotionContext throws INVALID_DATA when itemsContext is null/undefined, because buy-get rules (buy X get Y) cannot be evaluated without line items.

Source

Thrown at packages/modules/promotion/src/utils/compute-actions/buy-get.ts:33

import { areRulesValidForContext } from "../validations"
import { computeActionForBudgetExceeded } from "./usage"
import { Promotion } from "@models"

export type EligibleItem = {
  item_id: string
  quantity: BigNumberInput
}

function sortByPrice(a: ComputeActionItemLine, b: ComputeActionItemLine) {
  return MathBN.lt(a.subtotal, b.subtotal) ? 1 : -1
}

function isValidPromotionContext(
  promotion: PromotionTypes.PromotionDTO | InferEntityType<typeof Promotion>,
  itemsContext: ComputeActionItemLine[]
): boolean {
  if (!itemsContext) {
    throw new MedusaError(
      MedusaError.Types.INVALID_DATA,
      `"items" should be present as an array in the context to compute actions`
    )
  }

  if (!itemsContext?.length) {
    return false
  }

  const minimumBuyQuantity = MathBN.convert(
    promotion.application_method?.buy_rules_min_quantity ?? 0
  )

  if (
    MathBN.lte(minimumBuyQuantity, 0) ||
    !promotion.application_method?.buy_rules?.length
  ) {
    return false

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Populate context.items with the cart's line items mapped to ComputeActionItemLine (id, quantity, unit_price, etc.) before calling computeActions
  2. If computing only shipping adjustments, ensure the buy-get promotion code is not passed in the promotionCodes array
  3. Load the cart via CartModule and transform its items into the expected shape

Example fix

// before
await promotionModule.computeActions(["BUYGET_CODE"], {
  shipping_methods: [...],
})

// after
await promotionModule.computeActions(["BUYGET_CODE"], {
  items: cart.items.map((i) => ({
    id: i.id,
    quantity: i.quantity,
    unit_price: i.unit_price,
    variant_id: i.variant_id,
    product_id: i.product_id,
  })),
  shipping_methods: [...],
})
Defensive patterns

Strategy: validation

Validate before calling

const context = { ...rawContext, items: rawContext.items ?? [] }
if (!Array.isArray(context.items)) context.items = []

Type guard

const hasItemsContext = (ctx: Record<string, unknown>): boolean => Array.isArray(ctx.items)

Try / catch

try { await computeActions(codes, context) } catch (e) { if (e.type === MedusaError.Types.INVALID_DATA && /items.*context/.test(e.message)) { /* hydrate items from cart and retry */ } throw e }

Prevention

When it happens

Trigger: Calling promotionModule.computeActions([promoCode], {}) or with a context missing the items key while any applicable promotion is of type buyget; also passing items: null explicitly.

Common situations: Running computeActions for cart-level discounts without loading the cart first, reusing a shipping-only context (shipping_methods only) with a buy-get code, integration tests with empty context fixtures.

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/53ef55fe8d6dcfd4. Report an issue: GitHub.