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
- Check promotion.status === 'active' before submitting the code
- Re-activate/extend the promotion in the admin or via updatePromotions
- 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
- Check promotion status and validity window before advertising codes
- Deactivate ads/emails when promotions expire
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
- Promotion code "${missingPromoCodes[0]}" not found / Promoti
- A shipping method with id ${input.shipping_method_id} was no
- No item found for order ${input.order_id} in order change ${
- Action ${associatedAction.id} is not adding or updating an i
- No shipping method found for order ${input.order_id} in orde
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/62089c46b888b73a.
Report an issue: GitHub.