{"record":{"id":"46bf7f10240f29e6","repo":"different-ai/openwork","slug":"seat-checkout-failed-response-status","errorCode":null,"errorMessage":"Seat checkout failed (${response.status}).","messagePattern":"Seat checkout failed \\((.+?)\\)\\.","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/billing-dashboard-screen.tsx","lineNumber":293,"sourceCode":"    };\n  }, [sessionHydrated, user, orgContext?.organization.id]);\n\n  async function startSeatCheckout() {\n    if (!canManageBillingSettings) {\n      setStripeError(\"Admins can start seat checkout from Members. Owners and super-admins manage Billing settings here.\");\n      return;\n    }\n\n    setStripeError(null);\n    try {\n      await runReauthableAction(\"seat-checkout\", async () => {\n        setStripeActionBusy(\"seat-checkout\");\n        const { response, payload } = await requestJson(\n          \"/v1/billing/stripe/checkout\",\n          { method: \"POST\", body: JSON.stringify({ type: \"seat\" }) },\n          12000,\n        );\n        if (!response.ok) throw getRequestError(payload, response, `Seat checkout failed (${response.status}).`);\n        const url = payload && typeof payload === \"object\" && \"url\" in payload && typeof payload.url === \"string\" ? payload.url : null;\n        if (!url) throw new Error(\"Seat checkout response did not include a URL.\");\n        window.location.href = url;\n      });\n    } catch (error) {\n      setStripeError(error instanceof Error ? error.message : \"Could not start seat billing checkout.\");\n    } finally {\n      setStripeActionBusy(null);\n    }\n  }\n\n  async function openStripePortal() {\n    if (!canManageBillingSettings) {\n      setStripeError(\"Only workspace owners and super-admins can open billing portals from Settings.\");\n      return;\n    }\n\n    setStripeError(null);","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/billing-dashboard-screen.tsx#L275-L311","documentation":"Thrown by startSeatCheckout when the POST /v1/billing/stripe/checkout request (type \"seat\") returns a non-OK HTTP status. getRequestError first checks for a 403 reauth payload (throwing ReauthRequiredError instead) and otherwise surfaces the server's error message, falling back to this template that includes the status code. It indicates Stripe seat-subscription checkout could not be started server-side.","triggerScenarios":"The den-server /v1/billing/stripe/checkout endpoint replies 4xx/5xx: org has no Stripe customer/billing record yet, Stripe not configured on the server, payment_required/seat subscription state conflicts, 401 expired session, 403 requiring reauth, or 500 from a Stripe API failure.","commonSituations":"Self-hosted Den server without STRIPE keys configured; admin trying to buy seats before the org has a subscription; session expired mid-action; Stripe outage or webhook misconfiguration on the host.","solutions":["Inspect the thrown message / response body for the server's specific error (it overrides the fallback).","If the message is a reauth error, re-authenticate the admin session and retry (runReauthableAction handles this).","Verify Stripe API keys and webhook config on the Den server; checkout cannot start without them.","Confirm the org's billing state (no conflicting existing seat subscription) before retrying.","Retry after confirming status with GET billing status; if 5xx, check server logs for Stripe API errors."],"exampleFix":"// before\nif (!response.ok) throw getRequestError(payload, response, `Seat checkout failed (${response.status}).`);\nconst url = isRecord(payload) && typeof payload.url === \"string\" ? payload.url : null;\n// after\nif (!response.ok) {\n  const err = getRequestError(payload, response, `Seat checkout failed (${response.status}).`);\n  console.error(\"seat checkout failed\", response.status, payload);\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"const canCheckout = typeof window !== \"undefined\" && stripeConfigured; // check org billing status via GET /v1/billing first\nif (!orgBillingReady) return; // avoid POST when server has no Stripe customer","typeGuard":"function isCheckoutUrlPayload(p: unknown): p is { url: string } {\n  return typeof p === \"object\" && p !== null && \"url\" in p && typeof (p as { url: unknown }).url === \"string\";\n}","tryCatchPattern":"try {\n  await runReauthableAction(\"seat-checkout\", startSeatCheckout);\n} catch (error) {\n  if (isReauthRequiredError(error)) { promptReauth(); return; }\n  setStripeError(error instanceof Error ? error.message : \"Could not start seat billing checkout.\");\n}","preventionTips":["Check billing/org status via GET before attempting checkout","Always wrap in runReauthableAction so 403 reauth is retried transparently","Surface the server error message (getRequestError already does) rather than the raw fallback","Verify Stripe env config on the server before enabling billing UI","Treat 5xx as transient and offer a retry button"],"tags":["http","billing","stripe","network"],"backgroundTag":"stripe-checkout-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}