hcengineering/platform · error

Internal server error

Error message

Internal server error

What it means

Catch-all in handleStripeWebhook: after successful signature verification, any exception during event routing or handling (or constructing Stripe-related state) results in HTTP 500 'Internal server error'.

Source

Thrown at services/payment/pod-payment/src/providers/stripe/webhook.ts:100

            const subscriptionEvent = await createSubscriptionEventFromInvoiceEvent(ctx, stripe, event)
            if (subscriptionEvent == null) return

            await handleSubscriptionUpdated(ctx, accountsUrl, serviceToken, subscriptionEvent)
          } catch (err) {
            ctx.error('Failed to process Stripe invoice event', { event, err })
          }
        })()
        break
      }
      default: {
        ctx.info('Unhandled Stripe webhook event type', { type: event.type })
      }
    }

    res.status(200).json({ received: true })
  } catch (err) {
    ctx.error('Failed to process Stripe webhook', { err })
    res.status(500).json({ error: 'Internal server error' })
  }
}

/**
 * Handle subscription.created/updated/deleted
 */
async function handleSubscriptionUpdated (
  ctx: MeasureContext,
  accountsUrl: string,
  serviceToken: string,
  event: Stripe.Event
): Promise<void> {
  const subscription = event.data.object as Stripe.Subscription
  if (subscription == null) {
    ctx.error('Missing subscription data', { event })
    throw new Error('Missing subscription data')
  }

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Inspect server logs (ctx.error 'Failed to process Stripe webhook') for the root err and fix it
  2. Replay the event via Stripe dashboard or stripe CLI after the fix
  3. Make handlers idempotent (event.id dedupe) to survive Stripe's retries
  4. Add a default case that acknowledges unknown event types instead of throwing

Example fix

// before
default:
  throw new Error(`unhandled ${event.type}`)
// after
default:
  ctx.warn('Unhandled Stripe event', { type: event.type })
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await routeEvent(event)
  res.status(200).json({ received: true })
} catch (err) {
  ctx.error('Failed to process Stripe webhook', { err })
  res.status(500).json({ error: 'Internal server error' })
}

Prevention

When it happens

Trigger: A subscription event handler throws (DB failure, missing customer/price mapping, unexpected payload shape); unrecognized event type reaching code that assumes a structure; error thrown while building the response path after res already touched.

Common situations: Stripe schema changes adding fields/removing assumptions; DB outage during event processing; duplicate event replay hitting unique constraints.

Understand the failure class

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/4292397486169b67. Report an issue: GitHub.