payloadcms/payload · critical · Error
Stripe secret key is required.
Error message
Stripe secret key is required.
What it means
Thrown at the top of the Stripe initiatePayment adapter when props.secretKey is falsy. The Stripe SDK cannot be instantiated without a secret key, so initiate refuses to start. This is the initiate-side mirror of the confirmOrder secret-key check: a configuration error meaning the stripe adapter was registered without a secretKey.
Source
Thrown at packages/plugin-ecommerce/src/payments/adapters/stripe/initiatePayment.ts:26
appInfo?: Stripe.StripeConfig['appInfo']
secretKey: StripeAdapterArgs['secretKey']
}
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.')
}
View on GitHub (pinned to 00c58b35c0)
Solutions
- Set STRIPE_SECRET_KEY in every environment (dev/staging/prod) and load it before the config is built.
- Confirm the plugin reads that exact variable name and pass secretKey explicitly when constructing the adapter.
- Fail fast at boot: in payload.config.ts throw if !process.env.STRIPE_SECRET_KEY.
- Use Stripe test keys (sk_test_...) in non-prod so the flow is exercised in CI.
Example fix
// before
stripeAdapter({ secretKey: process.env.STRIPE_KEY }) // unset
// after
const secretKey = process.env.STRIPE_SECRET_KEY
if (!secretKey) throw new Error('STRIPE_SECRET_KEY is required')
stripeAdapter({ secretKey }) Defensive patterns
Strategy: validation
Validate before calling
function resolveStripeSecretKey(): string {
const key = process.env.STRIPE_SECRET_KEY
if (!key) throw new Error('STRIPE_SECRET_KEY is required to initiate Stripe payments')
return key
}
// register the adapter once at boot with the resolved key
stripePlugin({ stripe: { secretKey: resolveStripeSecretKey() } }) Type guard
export function hasSecretKey(props: unknown): props is { secretKey: string } {
return typeof (props as { secretKey?: unknown })?.secretKey === 'string' && (props as { secretKey: string }).secretKey.length > 0
} Try / catch
try {
await payments.initiatePayment({ data })
} catch (err) {
if (err instanceof Error && err.message === 'Stripe secret key is required.') {
// misconfiguration — do not retry; surface to ops
return { ok: false, reason: 'misconfigured-stripe' }
}
throw err
} Prevention
- Throw at boot if STRIPE_SECRET_KEY is unset so the failure is loud, not per-request.
- Confirm the env var name matches what the config reads.
- Use a Stripe test key in non-prod to exercise the flow.
- Share one adapter instance across initiate and confirm.
When it happens
Trigger: The ecommerce stripe adapter is registered with secretKey undefined/empty (e.g. secretKey: process.env.STRIPE_SECRET_KEY where the env var is unset) and initiatePayment is then called on that adapter.
Common situations: STRIPE_SECRET_KEY not set in the deployed environment; .env file missing or not loaded by the runtime; env var name mismatch between config and deployment; local dev without a Stripe test key; the key is set only for confirmOrder's code path via a different adapter instance.
Related errors
- Stripe secret key is required
- PaymentIntent ID is required
- No transaction found for the provided PaymentIntent ID
- Payment not completed.
- Cart ID not found in the PaymentIntent metadata
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/e0c7a6bbd2e72fc1.
Report an issue: GitHub.