payloadcms/payload · warning · Error
Variant with ID ${variant.id} is out of stock or does not ha
Error message
Variant with ID ${variant.id} is out of stock or does not have enough inventory. What it means
Thrown by defaultProductsValidation when a variant's inventory is exactly 0, or is a positive number less than the requested quantity. The check `variant.inventory === 0 || (variant.inventory && variant.inventory < quantity)` covers both out-of-stock and insufficient-stock for the variant branch. Inventory tracking is per variant when a variant is supplied.
Source
Thrown at packages/plugin-ecommerce/src/utilities/defaultProductsValidation.ts:24
currenciesConfig,
currency,
product,
quantity = 1,
variant,
}) => {
if (!currency) {
throw new Error('Currency must be provided for product validation.')
}
const priceField = `priceIn${currency.toUpperCase()}`
if (variant) {
if (!variant[priceField]) {
throw new Error(`Variant with ID ${variant.id} does not have a price in ${currency}.`)
}
if (variant.inventory === 0 || (variant.inventory && variant.inventory < quantity)) {
throw new Error(
`Variant with ID ${variant.id} is out of stock or does not have enough inventory.`,
)
}
} else if (product) {
// Validate the product's details only if the variant is not provided as it can have its own inventory and price
if (!product[priceField]) {
throw new Error(`Product does not have a price in.`, {
cause: { code: MissingPrice, codes: [product.id, currency] },
})
}
if (product.inventory === 0 || (product.inventory && product.inventory < quantity)) {
throw new Error(`Product is out of stock or does not have enough inventory.`, {
cause: { code: OutOfStock, codes: [product.id] },
})
}
}
}View on GitHub (pinned to 00c58b35c0)
Solutions
- Re-fetch variant inventory at checkout time and reject/reduce quantity if insufficient.
- Use optimistic inventory locking or atomic decrement on add-to-cart for high-demand items.
- Surface remaining stock to the customer and cap the selectable quantity.
- Decrement inventory atomically on order completion and reconcile with the source-of-truth inventory system.
Example fix
// before: stale inventory shown at checkout
const variant = await findByID(id) // inventory 0 by now
// after: re-read and clamp quantity at confirm time
const variant = await findByID(id)
if (variant.inventory < qty) qty = variant.inventory
if (qty === 0) throw new Error('Out of stock') Defensive patterns
Strategy: validation
Validate before calling
function variantHasStock(variant: { inventory?: number }, quantity: number): boolean {
if (variant.inventory === undefined) return true // untracked inventory
return variant.inventory === 0 ? false : variant.inventory >= quantity
}
if (!variantHasStock(variant, quantity)) {
throw new Error(`Only ${variant.inventory} units of variant ${variant.id} available`)
} Type guard
export function variantHasEnoughStock(variant: { inventory?: number }, quantity: number): boolean {
return typeof variant.inventory !== 'number' || variant.inventory >= quantity
} Try / catch
try {
defaultProductsValidation({ currency, variant, quantity })
} catch (err) {
if (err instanceof Error && /out of stock or does not have enough inventory/.test(err.message)) {
// clamp quantity to available stock and retry, or surface remaining quantity
const available = variant.inventory ?? 0
if (available > 0) return defaultProductsValidation({ currency, variant, quantity: available })
return { ok: false, reason: 'out-of-stock', variantId: variant.id }
}
throw err
} Prevention
- Re-fetch variant inventory at checkout time; do not trust long-lived client state.
- Decrement inventory atomically on order completion and reconcile with the source system.
- Cap the customer-selectable quantity to current stock on the product page.
- For high-demand items, use optimistic locking on add-to-cart to prevent oversell.
When it happens
Trigger: Cart validation/checkout where a variant's inventory is 0 or below the requested quantity. Triggered by defaultProductsValidation when variant is set and the price check passed but inventory is insufficient.
Common situations: Concurrent purchases depleting variant stock between add-to-cart and checkout; inventory not decremented after sales showing stale positive numbers; high-quantity orders exceeding available stock; admin set inventory to 0 to disable a variant; sync from an inventory system that hasn't propagated yet.
Related errors
- OutOfStock
- Variant with ID ${variant.id} does not have a price in ${cur
- PaymentIntent ID is required
- Cart items snapshot not found or invalid in the PaymentInten
- Currency is required.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/2858c3e1abc4d3c6.
Report an issue: GitHub.