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
- Inspect server logs (ctx.error 'Failed to process Stripe webhook') for the root err and fix it
- Replay the event via Stripe dashboard or stripe CLI after the fix
- Make handlers idempotent (event.id dedupe) to survive Stripe's retries
- 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
- Deduplicate on event.id for idempotent handling
- Acknowledge unknown event types with 200 + warn
- Alert on 500 responses and replay events after fixes
- Keep handler logic defensive against Stripe schema changes
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
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Related errors
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/4292397486169b67.
Report an issue: GitHub.