different-ai/openwork · error · Error
Checkout failed ( ).
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.
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
- Billing portal failed
- Seat checkout failed
- Failed to update inference settings
- Billing lookup failed
- Billing response was incomplete.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/a44cbfc1898b938a.
Report an issue: GitHub.
Appendix: 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)