different-ai/openwork · error
Seat billing checkout response did not include a URL.
Error message
Seat billing checkout response did not include a URL.
What it means
After the seat-checkout API call completes, startSeatCheckout expects the response payload to contain a string url field for the checkout session redirect. If the payload is missing, not an object, or its url is absent/non-string, the provider throws "Seat billing checkout response did not include a URL." rather than redirecting to an undefined location. This indicates a malformed or failed checkout-session response from the billing endpoint.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_providers/org-dashboard-provider.tsx:645
ensureActiveOrganizationSelected();
const { response, payload } = await requestJson(
"/v1/billing/stripe/checkout",
{
method: "POST",
body: JSON.stringify({ type: "seat" }),
},
12000,
);
if (!response.ok) {
throw getRequestError(payload, response, `Seat billing checkout failed (${response.status}).`);
}
const url = payload && typeof payload === "object" && "url" in payload && typeof payload.url === "string"
? payload.url
: null;
if (!url) {
throw new Error("Seat billing checkout response did not include a URL.");
}
window.location.href = url;
});
} finally {
setMutationBusy(null);
}
}
async function cancelInvitation(invitationId: string) {
if (!getCurrentAccess().canCancelInvitations) {
throw new Error("Only workspace admins can cancel invitations.");
}
await runMutation("cancel-invitation", async () => {
ensureActiveOrganizationSelected();
const { response, payload } = await requestJson(
`/v1/invitations/${encodeURIComponent(invitationId)}/cancel`,View on GitHub (pinned to 2b7df46e8a)
Solutions
- Inspect the network response of the seat-checkout request to see the actual payload shape.
- Retry the checkout; transient billing-provider issues can yield incomplete responses.
- Verify server and web app versions match the /v1 seat checkout contract (payload.url string).
- Report to the server team if the endpoint returns 2xx without url — the server should either return a URL or a non-2xx status.
Example fix
// before
const url = payload && typeof payload === "object" && "url" in payload && typeof payload.url === "string"
? payload.url : null;
if (!url) throw new Error("Seat billing checkout response did not include a URL.");
// after (server side: fail loudly instead of 2xx-without-url)
if (!checkoutSession?.url) {
return json({ error: "checkout_session_not_created" }, { status: 502 });
}
return json({ url: checkoutSession.url }); Defensive patterns
Strategy: type-guard
Validate before calling
function hasCheckoutUrl(p: unknown): p is { url: string } {
return typeof p === "object" && p !== null && "url" in p && typeof (p as { url: unknown }).url === "string" && (p as { url: string }).url.length > 0;
} Type guard
function isCheckoutPayload(p: unknown): p is { url: string } {
return typeof p === "object" && p !== null && "url" in p && typeof (p as { url: unknown }).url === "string";
} Try / catch
try {
await startSeatCheckout();
} catch (e) {
if (e instanceof Error && e.message.includes("did not include a URL")) {
showNotice("Checkout could not be started. Please retry or contact support.");
} else throw e;
} Prevention
- Assert the /v1 seat checkout contract (payload.url) in server tests.
- Treat 2xx-without-url as a server bug: return 502 with an error envelope instead.
- Monitor billing-provider errors that produce empty checkout sessions.
- Retry once on malformed checkout responses before surfacing to the user.
When it happens
Trigger: The POST that creates the seat checkout session returns 2xx with an unexpected body — e.g. an error envelope, an empty object, or a payload shaped { checkoutUrl } instead of { url } — inside the runReauthableAction callback.
Common situations: Billing provider outage or misconfigured Stripe return path causing the server to return a success status without a session URL; API contract changed between server and web versions; a proxy/CDN stripping or rewriting the response body; reauth flow returning a different payload shape.
Related errors
- invalid_billing_payload
- Billing lookup failed (${response.status}).
- Billing response was incomplete.
- Seat checkout failed (${response.status}).
- Billing portal failed (${response.status}).
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/e3adb13d11e9c658.
Report an issue: GitHub.