{"record":{"id":"e0c7a6bbd2e72fc1","repo":"payloadcms/payload","slug":"stripe-secret-key-is-required-e0c7a6","errorCode":null,"errorMessage":"Stripe secret key is required.","messagePattern":"Stripe secret key is required\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/plugin-ecommerce/src/payments/adapters/stripe/initiatePayment.ts","lineNumber":26,"sourceCode":"  appInfo?: Stripe.StripeConfig['appInfo']\n  secretKey: StripeAdapterArgs['secretKey']\n}\n\nexport const initiatePayment: (props: Props) => NonNullable<PaymentAdapter>['initiatePayment'] =\n  (props) =>\n  async ({ data, req, transactionsSlug }) => {\n    const payload = req.payload\n    const { apiVersion, appInfo, secretKey } = props || {}\n\n    const customerEmail = data.customerEmail\n    const currency = data.currency\n    const cart = data.cart\n    const amount = cart.subtotal\n    const billingAddressFromData = data.billingAddress\n    const shippingAddressFromData = data.shippingAddress\n\n    if (!secretKey) {\n      throw new Error('Stripe secret key is required.')\n    }\n\n    if (!currency) {\n      throw new Error('Currency is required.')\n    }\n\n    if (!cart || !cart.items || cart.items.length === 0) {\n      throw new Error('Cart is empty or not provided.')\n    }\n\n    if (!customerEmail || typeof customerEmail !== 'string') {\n      throw new Error('A valid customer email is required to make a purchase.')\n    }\n\n    if (!amount || typeof amount !== 'number' || amount <= 0) {\n      throw new Error('A valid amount is required to initiate a payment.')\n    }\n","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/plugin-ecommerce/src/payments/adapters/stripe/initiatePayment.ts#L8-L44","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nstripeAdapter({ secretKey: process.env.STRIPE_KEY }) // unset\n// after\nconst secretKey = process.env.STRIPE_SECRET_KEY\nif (!secretKey) throw new Error('STRIPE_SECRET_KEY is required')\nstripeAdapter({ secretKey })","handlingStrategy":"validation","validationCode":"function resolveStripeSecretKey(): string {\n  const key = process.env.STRIPE_SECRET_KEY\n  if (!key) throw new Error('STRIPE_SECRET_KEY is required to initiate Stripe payments')\n  return key\n}\n\n// register the adapter once at boot with the resolved key\nstripePlugin({ stripe: { secretKey: resolveStripeSecretKey() } })","typeGuard":"export function hasSecretKey(props: unknown): props is { secretKey: string } {\n  return typeof (props as { secretKey?: unknown })?.secretKey === 'string' && (props as { secretKey: string }).secretKey.length > 0\n}","tryCatchPattern":"try {\n  await payments.initiatePayment({ data })\n} catch (err) {\n  if (err instanceof Error && err.message === 'Stripe secret key is required.') {\n    // misconfiguration — do not retry; surface to ops\n    return { ok: false, reason: 'misconfigured-stripe' }\n  }\n  throw err\n}","preventionTips":["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."],"tags":["stripe","config","secrets","env","ecommerce"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}