{"record":{"id":"cf225c9f734a0d85","repo":"moeru-ai/airi","slug":"stripe-not-configured-is","errorCode":"STRIPE_NOT_CONFIGURED","errorMessage":"Stripe is not configured","messagePattern":"Stripe is not configured","errorType":"http","errorClass":"ApiError","httpStatus":503,"severity":"error","filePath":"server/apps/api/src/routes/stripe/operations/webhook.ts","lineNumber":94,"sourceCode":"  }).onConflictDoNothing()\n  return legacy.id\n}\n\n/**\n * Verifies a Stripe webhook, maps a Checkout Session to a claim receipt,\n * then calls Payment CORE. Unknown events are ignored.\n */\nexport function createWebhookOperation(\n  stripe: Stripe | null,\n  webhookSecret: string | null,\n  payment: PaymentService,\n  db: Database,\n  metrics: RevenueMetrics | null,\n  productEventService: ProductEventService | null,\n) {\n  return async (signature: string | null, body: string): Promise<{ received: true }> => {\n    if (!stripe || !webhookSecret)\n      throw createServiceUnavailableError('Stripe is not configured', 'STRIPE_NOT_CONFIGURED')\n\n    if (!signature)\n      throw createBadRequestError('No signature', 'MISSING_SIGNATURE')\n\n    let event: Stripe.Event\n    try {\n      event = stripe.webhooks.constructEvent(body, signature, webhookSecret)\n    }\n    catch (err: unknown) {\n      throw createBadRequestError(`Webhook Error: ${errorMessageFromUnknown(err)}`, 'WEBHOOK_ERROR')\n    }\n\n    logger.withFields({ type: event.type, id: event.id }).log('Webhook event received')\n    metrics?.stripeEvents.add(1, { event_type: event.type })\n\n    switch (event.type) {\n      case 'checkout.session.completed':\n      case 'checkout.session.async_payment_succeeded': {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/server/apps/api/src/routes/stripe/operations/webhook.ts#L76-L112","documentation":"The webhook operation requires an initialized Stripe client and a configured webhook signing secret. If either is missing, incoming webhook POSTs cannot be verified or processed, so it responds with 503 STRIPE_NOT_CONFIGURED before even checking the signature.","triggerScenarios":"Stripe POSTing to /webhooks/stripe (or a developer curling it) while stripe is null (no STRIPE_SECRET_KEY at init) or webhookSecret is null (STRIPE_WEBHOOK_SECRET unset).","commonSituations":"Deploying without setting STRIPE_WEBHOOK_SECRET; running the API locally without any Stripe environment; secret removed during rotation; webhook endpoint registered before backend config completed.","solutions":["Set STRIPE_WEBHOOK_SECRET (whsec_...) from the Stripe dashboard webhook endpoint settings.","Ensure the Stripe client initializes (STRIPE_SECRET_KEY present and valid).","Restart the API after adding the configuration.","If testing locally, use the Stripe CLI to forward events with a local secret configured."],"exampleFix":"// before (.env)\n# STRIPE_WEBHOOK_SECRET missing\n// after\nSTRIPE_WEBHOOK_SECRET=whsec_xxx","handlingStrategy":"try-catch","validationCode":"// Server-side startup check\nif (!process.env.STRIPE_SECRET_KEY || !process.env.STRIPE_WEBHOOK_SECRET)\n  throw new Error('Stripe webhook not configured')","typeGuard":null,"tryCatchPattern":"try {\n  await forwardWebhook(signature, body)\n} catch (e) {\n  if (e.code === 'STRIPE_NOT_CONFIGURED') {\n    // do not retry; configure the environment first\n  }\n}","preventionTips":["Include STRIPE_WEBHOOK_SECRET in deployment config checklists.","Fail server startup (or mark unhealthy) when Stripe config is missing in production.","Use Stripe CLI locally with a locally configured secret."],"tags":["stripe","webhook","configuration"],"backgroundTag":"missing-env-var","analyzedSha":"438a067dde47aa0bdb46c2323d1fe293dc805218","analyzedAt":"2026-09-17T01:14:42.644Z","contentChangedAt":"2026-09-17T01:14:42.644Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}