{"record":{"id":"6443de7a99de3fda","repo":"different-ai/openwork","slug":"billing-lookup-failed-response-status","errorCode":null,"errorMessage":"Billing lookup failed (${response.status}).","messagePattern":"Billing lookup failed \\((.+?)\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/billing-dashboard-screen.tsx","lineNumber":202,"sourceCode":"    orgContext?.currentMember.isOwner ?? false,\n    orgContext?.roles,\n  );\n  const canManageBillingSettings = access.canManageSettings;\n\n  async function refreshStripeBilling(quiet = false) {\n    const expectedOrgId = activeOrgId;\n    if (!expectedOrgId) return null;\n    const requestId = billingRequestIdRef.current + 1;\n    billingRequestIdRef.current = requestId;\n    setStripeBusy(true);\n    if (!quiet) setStripeError(null);\n    try {\n      const { response, payload } = await requestJson(\n        \"/v1/billing\",\n        { method: \"GET\", headers: { [ORG_SCOPE_HEADER]: expectedOrgId } },\n        12000,\n      );\n      if (!response.ok) throw new Error(getErrorMessage(payload, `Billing lookup failed (${response.status}).`));\n      const parsed = parseStripeBilling(payload);\n      if (!parsed) throw new Error(\"Billing response was incomplete.\");\n      if (currentOrgIdRef.current !== expectedOrgId || billingRequestIdRef.current !== requestId) return null;\n      setStripeBillingValue(parsed);\n      setStripeBillingOrgId(expectedOrgId);\n      setPolarBilling(parsePolarBilling(payload));\n      return parsed;\n    } catch (error) {\n      if (!quiet && currentOrgIdRef.current === expectedOrgId && billingRequestIdRef.current === requestId) {\n        setStripeError(error instanceof Error ? error.message : \"Could not load billing details.\");\n      }\n      return null;\n    } finally {\n      if (currentOrgIdRef.current === expectedOrgId && billingRequestIdRef.current === requestId) setStripeBusy(false);\n    }\n  }\n\n  useEffect(() => {","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/billing-dashboard-screen.tsx#L184-L220","documentation":"refreshStripeBilling GETs /v1/billing with an org-scope header and a 12s timeout. If response.ok is false, this error is thrown with the server message or a status fallback. It means the billing endpoint rejected the request, so no Stripe/Polar billing state is refreshed.","triggerScenarios":"GET /v1/billing returns 401 (expired session), 403 (missing/incorrect ORG_SCOPE_HEADER org membership), 404 (billing not enabled/self-hosted without billing), 429, or 5xx; expectedOrgId is stale after an org switch.","commonSituations":"User switched organizations and the ref carries an org they no longer belong to; Stripe not configured on the server; billing feature flag disabled; transient backend error.","solutions":["Check the status: 401 → re-authenticate; 403 → verify org membership and that expectedOrgId matches the current org; 404 → confirm billing is enabled on this Den server.","Retry after a transient 5xx/429; the function guards with requestId/currentOrgIdRef so stale results are ignored.","Verify Stripe configuration server-side if billing should exist.","Sign out/in to refresh session cookies if 401 persists."],"exampleFix":"// before\nif (!response.ok) throw new Error(getErrorMessage(payload, `Billing lookup failed (${response.status}).`));\n// after\nif (response.status === 403) throw new Error(\"You don't have access to billing for this organization.\");\nif (!response.ok) throw new Error(getErrorMessage(payload, `Billing lookup failed (${response.status}).`));","handlingStrategy":"retry","validationCode":"// Verify org scope header matches the active org before fetching billing\nif (!expectedOrgId) return null; // skip billing fetch\nconst membershipOk = await checkOrgMembership(expectedOrgId);\nif (!membershipOk) return null;","typeGuard":"function isStripeBilling(v: unknown): boolean {\n  return typeof v === \"object\" && v !== null && \"subscription\" in v;\n}","tryCatchPattern":"try {\n  await refreshStripeBilling(orgId);\n} catch (err) {\n  const m = err instanceof Error ? err.message : \"\";\n  if (m.includes(\"(401)\")) redirectToSignIn();\n  else if (m.includes(\"(403)\")) showToast(\"No billing access for this organization.\");\n  else if (/\\((5\\d\\d|429)\\)/.test(m)) setTimeout(() => refreshStripeBilling(orgId), 5000);\n  else showToast(m || \"Billing lookup failed\");\n}","preventionTips":["Always send the current org id in ORG_SCOPE_HEADER and refresh it on org switch.","Configure retry only for transient statuses (429, 5xx).","Gate the billing UI behind a server capability check (billing enabled).","The requestId/currentOrgIdRef guards already ignore stale results — keep them when refactoring."],"tags":["network","http-error","billing"],"backgroundTag":"http-request-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}