payloadcms/payload · error · Error
Currency is required.
Error message
Currency is required.
What it means
Thrown by Stripe initiatePayment when data.currency is falsy. Stripe requires a currency code (e.g. 'usd') to create a PaymentIntent, and the adapter also uses it to look up the correct price field per currency config. Omitting currency is an input-contract violation: the initiate request body must include currency.
Source
Thrown at packages/plugin-ecommerce/src/payments/adapters/stripe/initiatePayment.ts:30
export const initiatePayment: (props: Props) => NonNullable<PaymentAdapter>['initiatePayment'] =
(props) =>
async ({ data, req, transactionsSlug }) => {
const payload = req.payload
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 recognisedView on GitHub (pinned to 00c58b35c0)
Solutions
- Send data.currency as a lowercase ISO 4217 code (e.g. 'usd') in the initiatePayment request body.
- Default the currency server-side from the store config if the client omits it, before calling initiate.
- Validate currency client-side and disable the pay button until selected.
- Ensure the currency exists in currenciesConfig so downstream price lookups also succeed.
Example fix
// before
await payments.initiatePayment({ data: { cart, customerEmail } })
// after
await payments.initiatePayment({
data: { cart, customerEmail, currency: selectedCurrency },
}) Defensive patterns
Strategy: validation
Validate before calling
function resolveCurrency(value: unknown, fallback?: string): string {
if (typeof value === 'string' && /^[a-z]{3}$/i.test(value)) return value.toLowerCase()
if (fallback) return fallback.toLowerCase()
throw new Error('A valid 3-letter currency code is required')
}
// before initiatePayment
data.currency = resolveCurrency(data.currency, storeDefaultCurrency) Type guard
export function isCurrencyCode(value: unknown): value is string {
return typeof value === 'string' && /^[a-z]{3}$/i.test(value)
} Try / catch
try {
await payments.initiatePayment({ data })
} catch (err) {
if (err instanceof Error && err.message === 'Currency is required.') {
// prompt the customer to select a currency
return { ok: false, reason: 'currency-required' }
}
throw err
} Prevention
- Resolve currency once at checkout entry and thread it through every call.
- Default to the store's base currency when the customer hasn't selected one.
- Validate the currency is configured in currenciesConfig so downstream price lookups succeed.
- Disable the pay button until a valid currency is selected.
When it happens
Trigger: initiatePayment is called without data.currency, or with currency set to null/empty string. The check runs before any Stripe call, so it fails fast.
Common situations: Frontend checkout form that doesn't submit the currency field; multi-currency store where the selected currency isn't propagated to the initiate call; default currency not set and client assumes server fills it in; currency stored under a different key (e.g. currencyCode).
Related errors
- PaymentIntent ID is required
- A valid customer email is required to make a purchase.
- Currency must be provided for product validation.
- Cart items snapshot not found or invalid in the PaymentInten
- Cart is empty or not provided.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/5af86fff45bf75db.
Report an issue: GitHub.