payloadcms/payload · error · Error

Cart is empty or not provided.

Error message

Cart is empty or not provided.

What it means

Thrown by Stripe initiatePayment when data.cart is missing, has no items array, or items is empty. The adapter needs cart.items to compute the flattened snapshot stored in PaymentIntent metadata and to record the transaction. An empty cart cannot produce a valid payment, so initiation is refused before any Stripe call.

Source

Thrown at packages/plugin-ecommerce/src/payments/adapters/stripe/initiatePayment.ts:34

    const { apiVersion, appInfo, secretKey } = props || {}

    const customerEmail = data.customerEmail
    const currency = data.currency
    const cart = data.cart
    const amount = cart.subtotal
    const billingAddressFromData = data.billingAddress
    const shippingAddressFromData = data.shippingAddress

    if (!secretKey) {
      throw new Error('Stripe secret key is required.')
    }

    if (!currency) {
      throw new Error('Currency is required.')
    }

    if (!cart || !cart.items || cart.items.length === 0) {
      throw new Error('Cart is empty or not provided.')
    }

    if (!customerEmail || typeof customerEmail !== 'string') {
      throw new Error('A valid customer email is required to make a purchase.')
    }

    if (!amount || typeof amount !== 'number' || amount <= 0) {
      throw new Error('A valid amount is required to initiate a payment.')
    }

    const stripe = new Stripe(secretKey, {
      // API version can only be the latest, stripe recommends ts ignoring it
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore - ignoring since possible versions are not type safe, only the latest version is recognised
      apiVersion: apiVersion || '2025-06-30.preview',
      appInfo: appInfo || {
        name: 'Stripe Payload Plugin',
        url: 'https://payloadcms.com',

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Disable the checkout/pay button until the cart has at least one item.
  2. Fetch the cart server-side and ensure items is a non-empty array before calling initiatePayment.
  3. Validate cart structure client-side: assert Array.isArray(cart.items) && cart.items.length > 0.
  4. If using a cart slug with a different field name, map it to items before initiate.

Example fix

// before
await payments.initiatePayment({ data: { currency, customerEmail } }) // no cart
// after
if (!cart?.items?.length) throw new Error('Cart is empty')
await payments.initiatePayment({ data: { cart, currency, customerEmail } })
Defensive patterns

Strategy: type-guard

Validate before calling

export function isNonEmptyCart(cart: unknown): cart is { id: string; items: unknown[]; subtotal: number } {
  return (
    typeof cart === 'object' && cart !== null &&
    Array.isArray((cart as { items?: unknown }).items) &&
    ((cart as { items: unknown[] }).items.length > 0)
  )
}

if (!isNonEmptyCart(data.cart)) throw new Error('Cart must contain at least one item')
await payments.initiatePayment({ data })

Type guard

export function isNonEmptyCart(cart: unknown): cart is { items: unknown[] } {
  return typeof cart === 'object' && cart !== null && Array.isArray((cart as { items?: unknown }).items) && (cart as { items: unknown[] }).items.length > 0
}

Try / catch

try {
  await payments.initiatePayment({ data })
} catch (err) {
  if (err instanceof Error && /Cart is empty/.test(err.message)) {
    // prompt the customer to add items
    return { ok: false, reason: 'empty-cart', redirect: '/cart' }
  }
  throw err
}

Prevention

When it happens

Trigger: initiatePayment called with no cart, a cart object lacking items, or items: []. The check is `!cart || !cart.items || cart.items.length === 0`.

Common situations: Checkout button enabled on an empty cart; cart state lost between page and checkout; race where the cart is cleared before payment starts; cart stored under a different shape (e.g. data.items instead of data.cart.items); SSR-rendered page with no hydrated cart.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/7d24913f962aa6d9. Report an issue: GitHub.