moeru-ai/airi · error · ApiError
STRIPE_CHECKOUT_URL_MISSING
STRIPE_CHECKOUT_URL_MISSING
Error message
Stripe checkout did not return a URL
What it means
After creating a Stripe Checkout Session, the API expects session.url (the hosted payment page URL) to redirect the user. If Stripe returns a session without a URL, the pending order is abandoned and the API throws 503 STRIPE_CHECKOUT_URL_MISSING.
Solutions
- Retry the checkout; if transient, a fresh session should include the URL.
- Check the Stripe API version pinned by the server SDK against the expected response shape (session.url).
- Inspect the full session object in logs to see why URL is absent and adjust session creation parameters.
- Check Stripe status/incidents if it started failing broadly.
Example fix
// before
const session = await stripe.checkout.sessions.create(params)
return session.url // may be null
// after
const session = await stripe.checkout.sessions.create(params)
if (!session.url) throw createServiceUnavailableError('Stripe checkout did not return a URL', 'STRIPE_CHECKOUT_URL_MISSING')
return session.url Defensive patterns
Strategy: retry
Try / catch
try {
const { url } = await checkout(body)
} catch (e) {
if (e.code === 'STRIPE_CHECKOUT_URL_MISSING') {
// safe to retry: the pending order was abandoned server-side
await retryWithBackoff(() => checkout(body))
}
} Prevention
- Pin and test against a specific Stripe API version so session.url is always present.
- Monitor Stripe status pages and alert on checkout failure spikes.
- Log the full session object on this error to speed diagnosis.
When it happens
Trigger: stripe.checkout.sessions.create returning a session object with url === null/undefined, typically when the session was created in a mode/configuration that does not yield a hosted URL, or an unexpected Stripe API response.
Common situations: Stripe API version drift changing response shape; creating sessions with unusual parameters (e.g. custom payment method configurations); transient Stripe API incidents returning partial sessions.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
AI-assisted analysis of moeru-ai/airi@438a067dde (2026-09-17).
Data as JSON: /api/errors/80379d3ae63963f8.
Report an issue: GitHub.
Appendix: source
Thrown at server/apps/api/src/routes/stripe/operations/checkout.ts:99
if (Object.keys(paymentMethodOptions).length > 0)
sessionParams.payment_method_options = paymentMethodOptions as Stripe.Checkout.SessionCreateParams['payment_method_options']
if (currency)
sessionParams.currency = currency
let session: Stripe.Checkout.Session
try {
session = await stripe.checkout.sessions.create(sessionParams)
}
catch (error) {
await payment.abandon(order.id)
throw error
}
if (!session.url) {
await payment.abandon(order.id)
throw createServiceUnavailableError('Stripe checkout did not return a URL', 'STRIPE_CHECKOUT_URL_MISSING')
}
await payment.bindProcessorOrder(order.id, {
processorOrderId: session.id,
amount: session.amount_total ?? undefined,
currency: session.currency ?? currency,
})
metrics?.stripeCheckoutCreated.add(1)
void productEventService?.track({
userId: user.id,
feature: 'billing',
action: 'checkout_started',
status: 'succeeded',
eventId: order.id,
source: 'stripe.checkout',
metadata: {
stripe_price_id: stripePriceId,View on GitHub (pinned to 438a067dde)