different-ai/openwork · error · Error
Checkout failed (${response.status}).
Error message
Checkout failed (${response.status}). What it means
Thrown by startSubscribeCheckout when POST /v1/billing/stripe/checkout with type "inference" returns non-OK. getRequestError turns a 403 reauth payload into ReauthRequiredError and otherwise throws the server message or this fallback. It means the Stripe checkout session for inference usage subscription could not be created.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/inference-screen.tsx:359
// instead of bouncing the user to the billing page. Billing stays the
// status/portal view.
async function startSubscribeCheckout() {
if (!canManageModels) {
setError("Only workspace admins can start OpenWork Models checkout.");
return;
}
setError(null);
try {
await runReauthableAction("inference-checkout", async () => {
setSubscribeBusy(true);
const { response, payload } = await requestJson(
"/v1/billing/stripe/checkout",
{ method: "POST", body: JSON.stringify({ type: "inference" }) },
12000,
);
if (!response.ok) {
throw getRequestError(payload, response, `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("Checkout response did not include a URL.");
}
window.location.href = url;
});
} catch (checkoutError) {
setError(checkoutError instanceof Error ? checkoutError.message : "Could not start checkout.");
setSubscribeBusy(false);
}
}
async function toggleEnabled() {
if (!canManageModels) {
setError("Only workspace admins can manage OpenWork Models.");
return;
}View on GitHub (pinned to 2b7df46e8a)
Solutions
- Read the surfaced server message for the specific billing conflict.
- Re-authenticate if the error is reauth-required; runReauthableAction retries transparently.
- Verify Stripe configuration on the Den server (keys, webhooks, price IDs for inference).
- Refresh the inference status (GET) to see if a subscription already exists before retrying.
- On 5xx, check server logs for Stripe API errors.
Example fix
// before
if (!response.ok) {
throw getRequestError(payload, response, `Checkout failed (${response.status}).`);
}
// after
if (!response.ok) {
if (response.status === 409) throw new Error("You already have an inference subscription - open the billing portal instead.");
throw getRequestError(payload, response, `Checkout failed (${response.status}).`);
} Defensive patterns
Strategy: try-catch
Validate before calling
const { response, payload: status } = await requestJson("/v1/inference/status", {}, 10000);
if (status && typeof status === "object" && "subscribed" in status && status.subscribed === true) {
showToast("Already subscribed - use the billing portal to manage it."); return;
} Type guard
function isReauth(error: unknown): error is ReauthRequiredError { return error instanceof ReauthRequiredError; } Try / catch
try {
await runReauthableAction("inference-checkout", startSubscribeCheckout);
} catch (error) {
if (isReauthRequiredError(error)) { promptReauth(); return; }
setStripeError(error instanceof Error ? error.message : "Could not start checkout.");
} Prevention
- Check existing subscription state before starting checkout to avoid conflicts
- Verify Stripe env config server-side before showing the subscribe CTA
- Wrap in runReauthableAction to auto-handle reauth
- Disable the button while busy to prevent duplicate checkout sessions
When it happens
Trigger: POST /v1/billing/stripe/checkout (type "inference") fails: Stripe unconfigured on the server, org already subscribed or in an incompatible billing state (409/400), payment method/plan mismatch, expired session (401), or Stripe API 5xx. 12s timeout.
Common situations: Self-hosted Den without Stripe keys; clicking 'Subscribe' twice and hitting a state conflict; org switching between seat and inference subscriptions; Stripe outage.
Related errors
- Seat checkout failed (${response.status}).
- Billing portal failed (${response.status}).
- Failed to update inference settings (${response.status}).
- Failed to fetch latest-mac.yml (${response.status} ${respons
- Managed MCP outbound request exceeded the guarded redirect l
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/a44cbfc1898b938a.
Report an issue: GitHub.