{"record":{"id":"b60fd24b8718d829","repo":"medusajs/medusa","slug":"order-is-not-a-draft","errorCode":null,"errorMessage":"Order is not a draft","messagePattern":"Order is not a draft","errorType":"exception","errorClass":"MedusaError","httpStatus":400,"severity":"error","filePath":"packages/core/core-flows/src/draft-order/utils/validation.ts","lineNumber":14,"sourceCode":"import {\n  MedusaError,\n  OrderStatus,\n  PromotionStatus,\n} from \"@medusajs/framework/utils\"\nimport type { OrderDTO, PromotionDTO } from \"@medusajs/framework/types\"\n\ninterface ThrowIfNotDraftOrderInput {\n  order: OrderDTO\n}\n\nexport function throwIfNotDraftOrder({ order }: ThrowIfNotDraftOrderInput) {\n  if (order.status !== OrderStatus.DRAFT && !order.is_draft_order) {\n    throw new MedusaError(\n      MedusaError.Types.INVALID_DATA,\n      \"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","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/core/core-flows/src/draft-order/utils/validation.ts#L1-L32","documentation":"Shared utility behind validateDraftOrderChangeStep: any order-change operation on a draft order requires the order to be a draft (status DRAFT or is_draft_order flag); otherwise it throws INVALID_DATA.","triggerScenarios":"Any draft-order change workflow (add/update/remove items or promo codes) invoked on an order whose status is not draft and is_draft_order is falsy.","commonSituations":"Draft already confirmed; mixing up regular order edits with draft-order workflows; concurrent confirmation between read and write.","solutions":["Verify draft state (status/is_draft_order) before invoking the change workflow","Use order-edit workflows for non-draft orders","Refetch order state at operation time instead of trusting cached client state"],"exampleFix":"// before\nawait addDraftOrderItemsWorkflow(container).run({ input: { order_id: orderId, items: [...] } }) // non-draft order\n\n// after\nif (order.status === \"draft\" || order.is_draft_order) {\n  await addDraftOrderItemsWorkflow(container).run({ input: { order_id: orderId, items: [...] } })\n} else {\n  await beginOrderEditOrderWorkflow(container).run({ input: { order_id: orderId } })\n}","handlingStrategy":"type-guard","validationCode":"import { OrderStatus } from \"@medusajs/framework/utils\"\nif (order.status !== OrderStatus.DRAFT && !order.is_draft_order) {\n  // route to order-edit flows instead\n}","typeGuard":"const isDraftOrder = (o: { status: string; is_draft_order?: boolean }) => o.status === \"draft\" || !!o.is_draft_order","tryCatchPattern":null,"preventionTips":["Refetch order state at operation time","Disable draft-order UI actions once the order is confirmed"],"tags":["draft-order","order-status","validation"],"backgroundTag":"order-not-in-draft-state","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}