payloadcms/payload · error · Error
Unknown error initiating payment
Error message
Unknown error initiating payment
What it means
Thrown by the catch block at the end of Stripe initiatePayment when the caught error is not an Error instance. It is the fallback branch of error instanceof Error ? error.message : 'Unknown error initiating payment'. The original value is logged via payload.logger.error with msg 'Error initiating payment with Stripe' before the generic message is thrown, so the true cause is in the logs.
Source
Thrown at packages/plugin-ecommerce/src/payments/adapters/stripe/initiatePayment.ts:135
stripe: {
customerID: customer.id,
paymentIntentID: paymentIntent.id,
},
},
req,
})
const returnData: InitiatePaymentReturnType = {
clientSecret: paymentIntent.client_secret || '',
message: 'Payment initiated successfully',
paymentIntentID: paymentIntent.id,
}
return returnData
} catch (error) {
payload.logger.error({ err: error, msg: 'Error initiating payment with Stripe' })
throw new Error(error instanceof Error ? error.message : 'Unknown error initiating payment')
}
}
View on GitHub (pinned to 00c58b35c0)
Solutions
- Inspect the Payload log entry (msg 'Error initiating payment with Stripe', field err) for the real cause.
- Reproduce locally and log typeof error, error, and (error as any)?.constructor?.name.
- Align the stripe package version with the adapter's expectations.
- Normalize third-party rejections to Error objects before they reach the adapter.
Example fix
// before: dependency throws a non-Error
throw { status: 400 } // surfaces as 'Unknown error initiating payment'
// after
throw new Error('Request failed with status 400') Defensive patterns
Strategy: try-catch
Validate before calling
// Normalize third-party rejections to Error instances before they reach the adapter
async function safeStripeCall<T>(fn: () => Promise<T>): Promise<T> {
try {
return await fn()
} catch (e) {
if (e instanceof Error) throw e
throw new Error(typeof e === 'string' ? e : JSON.stringify(e))
}
} Type guard
export function isErrorLike(e: unknown): e is Error {
return e instanceof Error || (typeof e === 'object' && e !== null && typeof (e as { message?: unknown }).message === 'string')
} Try / catch
try {
await payments.initiatePayment({ data })
} catch (err) {
if (err instanceof Error && err.message === 'Unknown error initiating payment') {
// consult server logs: msg 'Error initiating payment with Stripe' carries the original err
return { ok: false, reason: 'unknown-initiate-error', checkLogs: true }
}
throw err
} Prevention
- Read the Payload log entry for the original err object — the thrown message is generic by design.
- Pin the stripe package version known to reject with Error instances.
- Wrap third-party calls so they reject with Error objects before reaching the adapter.
- Add structured logging that records error.constructor.name and the full error.
When it happens
Trigger: Any non-Error value thrown inside initiatePayment's try block — e.g. a dependency rejecting with a string, a malformed Stripe response parsed into a plain object, or a polyfill that throws non-Error values. Error-typed throws surface their own message; only non-Error throws reach this branch.
Common situations: Stripe SDK version mismatch producing non-Error rejections; a custom middleware throwing a string; JSON.stringify failing on circular cart data and a wrapper converting it; fetch polyfills in older Node versions; misconfigured proxy throwing plain objects.
Related errors
- Unknown error initiating payment
- Stripe secret key is required
- PaymentIntent ID is required
- No transaction found for the provided PaymentIntent ID
- Payment not completed.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/fe145606ac591f87.
Report an issue: GitHub.