medusajs/medusa · error · MedusaError

Order is not a draft

Error message

Order is not a draft

What it means

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.

Source

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

import {
  MedusaError,
  OrderStatus,
  PromotionStatus,
} from "@medusajs/framework/utils"
import type { OrderDTO, PromotionDTO } from "@medusajs/framework/types"

interface ThrowIfNotDraftOrderInput {
  order: OrderDTO
}

export function throwIfNotDraftOrder({ order }: ThrowIfNotDraftOrderInput) {
  if (order.status !== OrderStatus.DRAFT && !order.is_draft_order) {
    throw new MedusaError(
      MedusaError.Types.INVALID_DATA,
      "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)
  )

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Verify draft state (status/is_draft_order) before invoking the change workflow
  2. Use order-edit workflows for non-draft orders
  3. Refetch order state at operation time instead of trusting cached client state

Example fix

// before
await addDraftOrderItemsWorkflow(container).run({ input: { order_id: orderId, items: [...] } }) // non-draft order

// after
if (order.status === "draft" || order.is_draft_order) {
  await addDraftOrderItemsWorkflow(container).run({ input: { order_id: orderId, items: [...] } })
} else {
  await beginOrderEditOrderWorkflow(container).run({ input: { order_id: orderId } })
}
Defensive patterns

Strategy: type-guard

Validate before calling

import { OrderStatus } from "@medusajs/framework/utils"
if (order.status !== OrderStatus.DRAFT && !order.is_draft_order) {
  // route to order-edit flows instead
}

Type guard

const isDraftOrder = (o: { status: string; is_draft_order?: boolean }) => o.status === "draft" || !!o.is_draft_order

Prevention

When it happens

Trigger: 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.

Common situations: Draft already confirmed; mixing up regular order edits with draft-order workflows; concurrent confirmation between read and write.

Related errors


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