{"record":{"id":"8dd4011588b95ff6","repo":"medusajs/medusa","slug":"promotion-code-missingpromocodes-0-not-found","errorCode":null,"errorMessage":"Promotion code \"${missingPromoCodes[0]}\" not found / Promotion codes \"${missingPromoCodes.join('\", \"')}\" not found","messagePattern":"Promotion code \"(.+?)\" not found / Promotion codes \"(.+?)\" not found","errorType":"exception","errorClass":"MedusaError","httpStatus":400,"severity":"error","filePath":"packages/core/core-flows/src/draft-order/utils/validation.ts","lineNumber":34,"sourceCode":"      \"Order is not a draft\"\n    )\n  }\n}\n\nfunction getMessageByCount(count: number, singular: string, plural: string) {\n  return count === 1 ? singular : plural\n}\n\nexport function throwIfCodesAreMissing(\n  promo_codes: string[],\n  promotions: PromotionDTO[]\n) {\n  const missingPromoCodes = promo_codes.filter(\n    (code) => !promotions.some((promotion) => promotion.code === code)\n  )\n\n  if (missingPromoCodes.length > 0) {\n    throw new MedusaError(\n      MedusaError.Types.INVALID_DATA,\n      getMessageByCount(\n        missingPromoCodes.length,\n        `Promotion code \"${missingPromoCodes[0]}\" not found`,\n        `Promotion codes \"${missingPromoCodes.join('\", \"')}\" not found`\n      )\n    )\n  }\n}\n\nexport function throwIfCodesAreInactive(\n  promo_codes: string[],\n  promotions: PromotionDTO[]\n) {\n  const inactivePromoCodes = promo_codes.filter((code) =>\n    promotions.some(\n      (promotion) =>\n        promotion.code === code && promotion.status !== PromotionStatus.ACTIVE","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/core/core-flows/src/draft-order/utils/validation.ts#L16-L52","documentation":"throwIfCodesAreMissing (used by validatePromoCodesToAddStep/ToRemoveStep) verifies every promo code passed exists among the fetched promotions; missing codes throw INVALID_DATA.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify each code against promotion.listPromotions({ code: [...] }) before calling the workflow","Create or re-enable the promotion in this environment","Normalize/validate user-entered codes (trim, case) against the code list"],"exampleFix":"// before\nawait addDraftOrderPromotionsWorkflow(container).run({ input: { order_id, promo_codes: [\"WELCOME10\"] } }) // code deleted\n\n// after\nconst promos = await promotionModule.listPromotions({ code: [\"WELCOME10\"] })\nif (promos.length === 1) {\n  await addDraftOrderPromotionsWorkflow(container).run({ input: { order_id, promo_codes: [\"WELCOME10\"] } })\n} else {\n  throw new Error(\"Invalid promo code\")\n}","handlingStrategy":"validation","validationCode":"const promos = await promotionModule.listPromotions({ code: promo_codes })\nconst missing = promo_codes.filter((c) => !promos.some((p) => p.code === c))\nif (missing.length) throw new Error(`Unknown codes: ${missing.join(\", \")}`)","typeGuard":null,"tryCatchPattern":"try { await workflow(scope).run({ input }) } catch (e) { if (/Promotion code(s)? .* not found/.test(e.message)) { /* show friendly invalid-code message */ } throw e }","preventionTips":["Trim and case-normalize user-entered codes","Validate codes against listPromotions before submission"],"tags":["promotion","promo-code","draft-order","not-found"],"backgroundTag":"promo-code-not-found","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}