payloadcms/payload · error · Error
A valid amount is required to initiate a payment.
Error message
A valid amount is required to initiate a payment.
What it means
Thrown by Stripe initiatePayment when amount (cart.subtotal) is falsy, not a number, or <= 0. Stripe requires a positive integer amount in the smallest currency unit. The adapter derives amount = cart.subtotal at the top of the function, so a cart without a numeric subtotal, or with subtotal 0, triggers this guard before any Stripe call.
Source
Thrown at packages/plugin-ecommerce/src/payments/adapters/stripe/initiatePayment.ts:42
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',
},
})
try {
let customer = (
await stripe.customers.list({
email: customerEmail,
})View on GitHub (pinned to 00c58b35c0)
Solutions
- Compute cart.subtotal server-side as a positive integer (cents) before initiatePayment.
- For zero-amount carts (free items), short-circuit: skip Stripe and create the order directly.
- Ensure subtotal is a Number, not a string, before calling initiate.
- Validate amount >= 50 (Stripe's minimum in many currencies) to avoid Stripe-side rejections.
Example fix
// before: subtotal undefined or string
const cart = { items, subtotal: undefined }
// after: compute positive integer cents
const subtotal = items.reduce((s, i) => s + i.price * i.quantity, 0)
if (!(subtotal > 0)) throw new Error('Invalid subtotal')
const cart = { items, subtotal } Defensive patterns
Strategy: validation
Validate before calling
function resolveAmount(subtotal: unknown): number {
if (typeof subtotal !== 'number' || !Number.isFinite(subtotal) || subtotal <= 0) {
throw new Error('A positive numeric subtotal (in smallest currency unit) is required')
}
return Math.round(subtotal)
}
// before initiatePayment — for zero-amount carts, skip Stripe and create the order directly
data.cart.subtotal = resolveAmount(data.cart.subtotal) Type guard
export function isPositiveAmount(value: unknown): value is number {
return typeof value === 'number' && Number.isFinite(value) && value > 0
} Try / catch
try {
await payments.initiatePayment({ data })
} catch (err) {
if (err instanceof Error && /valid amount/.test(err.message)) {
if (cart.subtotal === 0) {
// free order — bypass Stripe
return await createFreeOrder(cart)
}
return { ok: false, reason: 'invalid-amount' }
}
throw err
} Prevention
- Compute cart.subtotal server-side as a positive integer (cents) before initiatePayment.
- Short-circuit zero-amount carts to a non-Stripe order flow (Stripe does not allow 0-amount intents).
- Ensure subtotal is a Number, not a string, before calling initiate.
- Validate amount >= Stripe's minimum for the currency to avoid downstream rejections.
When it happens
Trigger: cart.subtotal is undefined, null, a string, 0, or negative when initiatePayment runs. The check is `!amount || typeof amount !== 'number' || amount <= 0`.
Common situations: Cart subtotal not computed before checkout (client relies on server to total); free-cart edge case where subtotal legitimately is 0 (Stripe does not support zero-amount intents — use a different flow); subtotal stored as a string from a form; rounding producing 0 for tiny carts; currency-conversion bug yielding 0.
Related errors
- Cart items snapshot not found or invalid in the PaymentInten
- Cart is empty or not provided.
- PaymentIntent ID is required
- Cart ID not found in the PaymentIntent metadata
- Currency is required.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/250ca595b487e8f9.
Report an issue: GitHub.