{"record":{"id":"ba7b9e1d67d5ce45","repo":"payloadcms/payload","slug":"outofstock","errorCode":"OutOfStock","errorMessage":"Product is out of stock or does not have enough inventory.","messagePattern":"Product is out of stock or does not have enough inventory\\.","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/plugin-ecommerce/src/utilities/defaultProductsValidation.ts","lineNumber":37,"sourceCode":"    if (!variant[priceField]) {\n      throw new Error(`Variant with ID ${variant.id} does not have a price in ${currency}.`)\n    }\n\n    if (variant.inventory === 0 || (variant.inventory && variant.inventory < quantity)) {\n      throw new Error(\n        `Variant with ID ${variant.id} is out of stock or does not have enough inventory.`,\n      )\n    }\n  } else if (product) {\n    // Validate the product's details only if the variant is not provided as it can have its own inventory and price\n    if (!product[priceField]) {\n      throw new Error(`Product does not have a price in.`, {\n        cause: { code: MissingPrice, codes: [product.id, currency] },\n      })\n    }\n\n    if (product.inventory === 0 || (product.inventory && product.inventory < quantity)) {\n      throw new Error(`Product is out of stock or does not have enough inventory.`, {\n        cause: { code: OutOfStock, codes: [product.id] },\n      })\n    }\n  }\n}\n","sourceCodeStart":19,"sourceCodeEnd":43,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/plugin-ecommerce/src/utilities/defaultProductsValidation.ts#L19-L43","documentation":"Thrown by defaultProductsValidation when no variant is supplied and the product's inventory is 0 or less than the requested quantity. The check `product.inventory === 0 || (product.inventory && product.inventory < quantity)` covers both fully out-of-stock and insufficient stock for the product branch. The error carries an ErrorOptions cause with code 'OutOfStock' and codes [product.id] for programmatic handling.","triggerScenarios":"Cart/checkout validation where a product (no variant) has inventory 0 or below the requested quantity. Triggered in the product branch after the price check passed.","commonSituations":"Sales depleting stock between add-to-cart and checkout; stale inventory cache; admin marking a product out of stock (inventory 0) without unpublishing; bulk orders exceeding available quantity; inventory sync delay from an external system.","solutions":["Re-fetch product inventory at checkout and reject or clamp the quantity.","Decrement inventory atomically on order completion and reconcile with the source system.","Cap the customer-selectable quantity to current stock on the product page.","Inspect error.cause.code === 'OutOfStock' to show a precise 'back in stock soon' message and capture demand (email signup)."],"exampleFix":"// before: stale stock at checkout\nconst product = await findByID(id) // inventory 0\n// after: re-read and clamp at confirm\nconst product = await findByID(id)\nif (product.inventory < qty) qty = product.inventory\nif (qty === 0) throw new Error('Out of stock')","handlingStrategy":"try-catch","validationCode":"function productHasStock(product: { inventory?: number }, quantity: number): boolean {\n  if (product.inventory === undefined) return true // untracked inventory\n  return product.inventory === 0 ? false : product.inventory >= quantity\n}\n\nif (!productHasStock(product, quantity)) {\n  const e = new Error(`Product ${product.id} is out of stock`)\n  ;(e as any).cause = { code: 'OutOfStock', codes: [product.id] }\n  throw e\n}","typeGuard":"export function productHasEnoughStock(product: { inventory?: number }, quantity: number): boolean {\n  return typeof product.inventory !== 'number' || product.inventory >= quantity\n}","tryCatchPattern":"try {\n  defaultProductsValidation({ currency, product, quantity })\n} catch (err) {\n  const cause = (err as Error & { cause?: { code?: string } }).cause\n  if (cause?.code === 'OutOfStock') {\n    // clamp quantity to available stock and retry, or surface a back-in-stock prompt\n    const available = product.inventory ?? 0\n    if (available > 0) return defaultProductsValidation({ currency, product, quantity: available })\n    return { ok: false, reason: 'out-of-stock', productId: product.id }\n  }\n  throw err\n}","preventionTips":["Re-read product inventory at checkout; don't trust long-lived client state.","Decrement inventory atomically on order completion and reconcile with the inventory source.","Cap selectable quantity to current stock on the product page.","Inspect error.cause.code === 'OutOfStock' to show precise messaging and capture waitlist demand."],"tags":["validation","product","inventory","ecommerce","stock","error-code"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}