Significant-Gravitas/AutoGPT · error · Error
Stripe didn't return a checkout URL. Check backend logs for
Error message
Stripe didn't return a checkout URL. Check backend logs for the underlying Stripe error.
What it means
Thrown by the BalanceCard top-up flow when the checkout request returned 2xx but the response body contains no checkout_url. This means the backend explicitly succeeded without producing a Stripe checkout session URL — per the code comment, the underlying reason (Stripe error swallowed, config issue) is only visible in backend logs, which is why the message points there.
Source
Thrown at autogpt_platform/frontend/src/app/(platform)/settings/billing/components/AutomationCreditsTab/BalanceCard/useBalanceCard.ts:71
// ``{"detail": "..."}``) instead of the generic "no URL" message —
// the actual failure is almost always a Stripe-side error
// (stale customer ID, missing product, invalid API key) that the
// user / their team needs to see to fix.
const detail =
typeof body?.detail === "string"
? body.detail
: (body?.detail?.msg ?? `Server returned ${status}.`);
throw new Error(detail);
}
const url = body?.checkout_url;
if (url) {
// Navigating away — don't touch React state on the unmounting tree.
window.location.href = url;
return;
}
throw new Error(
"Stripe didn't return a checkout URL. Check backend logs for the underlying Stripe error.",
);
} catch (error) {
toast({
title: "Couldn't start checkout",
description:
error instanceof Error
? error.message
: "Something went wrong contacting Stripe. Please try again.",
variant: "destructive",
});
}
}
return {
balanceCents: balanceCents ?? null,
isLoading,
isError,View on GitHub (pinned to 9c8bb5550f)
Solutions
- Read backend logs at the moment of the click — the message is designed to send you there; look for swallowed Stripe exceptions.
- Verify Stripe env vars on the backend container are set and the key is valid (a quick curl of the Stripe API with the same key confirms).
- Inspect the actual 2xx response body in DevTools to see what the backend returned instead of checkout_url.
- If it's a backend code path issue, fix the endpoint to fail with 4xx/5xx + detail instead of 200-with-no-URL (the frontend is already prepared to surface detail).
Example fix
// backend: before
try:
session = stripe.checkout.Session.create(...)
except stripe.StripeError:
pass # returns 200 with no checkout_url
// backend: after
except stripe.StripeError as e:
raise HTTPException(status_code=502, detail=str(e)) Defensive patterns
Strategy: validation
Validate before calling
function hasCheckoutUrl(body: unknown): body is { checkout_url: string } {
return typeof body === "object" && body !== null &&
typeof (body as any).checkout_url === "string" &&
(body as any).checkout_url.startsWith("https://");
} Type guard
function isMissingCheckoutUrl(err: unknown): boolean {
return err instanceof Error && err.message.startsWith("Stripe didn't return a checkout URL");
} Try / catch
try {
await startCheckout(amount);
} catch (error) {
if (isMissingCheckoutUrl(error)) {
// backend-side issue by definition: escalate to operator/backend logs, no user retry helps
}
} Prevention
- Treat 200-without-checkout_url as a backend contract violation — fix the endpoint to fail loudly with 4xx/5xx + detail.
- Type-guard checkout_url before navigating; don't window.location.assign undefined.
- Add backend telemetry on the Stripe session-creation path so 'check backend logs' always has something to find.
When it happens
Trigger: POST create-checkout returning 200/201 with {checkout_url: null/undefined/missing} — backend caught a Stripe error and returned a success-shaped response, or a code path forgot to include the URL (e.g. user already has an active session, or an early-return path).
Common situations: Backend bug swallowing StripeError into a 200; misconfigured STRIPE_SECRET_KEY making session.create return nothing useful; race where a previous checkout session is reused but the URL isn't propagated.
Related errors
- Server returned ${status}.
- str(e)
- success_url and cancel_url are required for paid tier upgrad
- str(e)
- Rate limit reset is not available (credit system is disabled
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/751962866b2c8462.
Report an issue: GitHub.