medusajs/medusa · error · MedusaError
invalid_data
invalid_data
Error message
Variant does not have a product
What it means
prepareLineItemData requires that, when a variant is supplied, it carries its parent product (used for title/thumbnail/metadata on the line item). If variant is present but variant.product is undefined, the utility throws because it cannot construct a valid line item.
Source
Thrown at packages/core/core-flows/src/cart/utils/prepare-line-item-data.ts:96
cartId?: string
unitPrice?: BigNumberInput
isTaxInclusive: boolean
}
export function prepareLineItemData(data: PrepareLineItemDataInput) {
const {
item,
variant,
cartId,
taxLines,
adjustments,
isCustomPrice,
unitPrice,
isTaxInclusive,
} = data
if (variant && !variant.product) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Variant does not have a product"
)
}
if (item && MathBN.lte(item.quantity, 0)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Item quantity must be greater than 0"
)
}
let compareAtUnitPrice = item?.compare_at_unit_price
const isSalePrice =
variant?.calculated_price?.calculated_price?.price_list_type ===
PriceListType.SALE
View on GitHub (pinned to 5e06e544a2)
Solutions
- Ensure the variant passed in includes the product relation (include 'product.*' when querying variants)
- If building input manually, fetch the product and attach it before calling the utility
- Repair broken variant-product links in the Product module if the relation is genuinely missing
Example fix
// before
const variants = await query.graph({ entity: 'variant', filters: { id: variantIds }, fields: ['*'] })
const item = prepareLineItemData({ variant: variants[0], quantity: 1 })
// after
const variants = await query.graph({ entity: 'variant', filters: { id: variantIds }, fields: ['*', 'product.*'] })
const item = prepareLineItemData({ variant: variants[0], quantity: 1 }) Defensive patterns
Strategy: validation
Validate before calling
if (input.variant && !input.variant.product) {
throw new Error('Load the variant with its product relation before preparing line item data')
} Type guard
const variantWithProduct = (
v: VariantDTO
): v is VariantDTO & { product: ProductDTO } => Boolean(v.product) Prevention
- Always select 'product.*' when fetching variants used for cart operations
- Type your inputs as Variant & { product: Product } so the compiler enforces the relation
When it happens
Trigger: Calling prepareLineItemData (directly or via addToCartWorkflow / updateLineItemsWorkflow) with a variant object that was fetched without the product relation, or a variant whose link to its product is broken.
Common situations: Custom code or plugins loading variants with remoteQuery/graph without selecting product; stale or corrupted variant-product links after data imports; passing a partially-built variant DTO instead of a full variant.
Related errors
- Variants ${variantNotFoundOrPublished.join( ", "
- Variants with IDs ${priceNotFound.join(", ")} do not have a
- Line item with id: ${input.item_id} was not found
- Line item ${item.title} has no unit price
- invalid_data
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/9c94f749e1b9d191.
Report an issue: GitHub.