medusajs/medusa · error · MedusaError

Promotion code "${missingPromoCodes[0]}" not found / Promoti

Error message

Promotion code "${missingPromoCodes[0]}" not found / Promotion codes "${missingPromoCodes.join('", "')}" not found

What it means

throwIfCodesAreMissing (used by validatePromoCodesToAddStep/ToRemoveStep) verifies every promo code passed exists among the fetched promotions; missing codes throw INVALID_DATA.

Source

Thrown at packages/core/core-flows/src/draft-order/utils/validation.ts:34

      "Order is not a draft"
    )
  }
}

function getMessageByCount(count: number, singular: string, plural: string) {
  return count === 1 ? singular : plural
}

export function throwIfCodesAreMissing(
  promo_codes: string[],
  promotions: PromotionDTO[]
) {
  const missingPromoCodes = promo_codes.filter(
    (code) => !promotions.some((promotion) => promotion.code === code)
  )

  if (missingPromoCodes.length > 0) {
    throw new MedusaError(
      MedusaError.Types.INVALID_DATA,
      getMessageByCount(
        missingPromoCodes.length,
        `Promotion code "${missingPromoCodes[0]}" not found`,
        `Promotion codes "${missingPromoCodes.join('", "')}" not found`
      )
    )
  }
}

export function throwIfCodesAreInactive(
  promo_codes: string[],
  promotions: PromotionDTO[]
) {
  const inactivePromoCodes = promo_codes.filter((code) =>
    promotions.some(
      (promotion) =>
        promotion.code === code && promotion.status !== PromotionStatus.ACTIVE

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Verify each code against promotion.listPromotions({ code: [...] }) before calling the workflow
  2. Create or re-enable the promotion in this environment
  3. Normalize/validate user-entered codes (trim, case) against the code list

Example fix

// before
await addDraftOrderPromotionsWorkflow(container).run({ input: { order_id, promo_codes: ["WELCOME10"] } }) // code deleted

// after
const promos = await promotionModule.listPromotions({ code: ["WELCOME10"] })
if (promos.length === 1) {
  await addDraftOrderPromotionsWorkflow(container).run({ input: { order_id, promo_codes: ["WELCOME10"] } })
} else {
  throw new Error("Invalid promo code")
}
Defensive patterns

Strategy: validation

Validate before calling

const promos = await promotionModule.listPromotions({ code: promo_codes })
const missing = promo_codes.filter((c) => !promos.some((p) => p.code === c))
if (missing.length) throw new Error(`Unknown codes: ${missing.join(", ")}`)

Try / catch

try { await workflow(scope).run({ input }) } catch (e) { if (/Promotion code(s)? .* not found/.test(e.message)) { /* show friendly invalid-code message */ } throw e }

Prevention

When it happens

Trigger: Adding or removing promo codes on a draft order with one or more codes that don't exist in the promotion module (typo, deleted promotion, wrong environment).

Common situations: User pastes an old/expired code that was deleted; promotion created in a different environment (staging vs prod); case-sensitivity mismatch; client sends code trimmed incorrectly.

Related errors


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