medusajs/medusa · error · MedusaError

Promotion code "${inactivePromoCodes[0]}" is not active / Pr

Error message

Promotion code "${inactivePromoCodes[0]}" is not active / Promotion codes "${inactivePromoCodes.join('", "')}" are not active

What it means

throwIfCodesAreInactive (used by validatePromoCodesToAddStep) checks that every matched promotion has status ACTIVE; adding an inactive/draft/expired promotion code to a draft order throws.

Source

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

        `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
    )
  )

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

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Check promotion.status === 'active' before submitting the code
  2. Re-activate/extend the promotion in the admin or via updatePromotions
  3. Provide a friendly 'code no longer active' message to the customer instead of surfacing the raw error

Example fix

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

// after
const [promo] = await promotionModule.listPromotions({ code: ["WELCOME10"] })
if (promo?.status === "active") {
  await addDraftOrderPromotionsWorkflow(container).run({ input: { order_id, promo_codes: ["WELCOME10"] } })
} else {
  throw new Error("This code is no longer active")
}
Defensive patterns

Strategy: validation

Validate before calling

const promos = await promotionModule.listPromotions({ code: promo_codes })
const inactive = promos.filter((p) => p.status !== "active").map((p) => p.code)
if (inactive.length) throw new Error(`Codes not active: ${inactive.join(", ")}`)

Type guard

const isActivePromo = (p: { status: string }) => p.status === "active"

Try / catch

try { await workflow(scope).run({ input }) } catch (e) { if (/not active/.test(e.message)) { /* show 'code no longer active' message */ } throw e }

Prevention

When it happens

Trigger: Adding a promo code whose promotion exists but has status inactive/draft/expired (status !== 'ACTIVE') on a draft order.

Common situations: Promotion disabled after publish; scheduled promotion not yet active; promotion expired but code still advertised; admin created the promotion but never activated it.

Related errors


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