{"record":{"id":"e246fb4173fcb0c6","repo":"antiwork/gumroad","slug":"request-failed-response-status","errorCode":null,"errorMessage":"Request failed (${response.status})","messagePattern":"Request failed \\((.+?)\\)","errorType":"exception","errorClass":"ResponseError","httpStatus":null,"severity":"error","filePath":"app/javascript/components/Settings/PaymentsPage/BeneficialOwnersSection.tsx","lineNumber":458,"sourceCode":"    if (formError) formErrorRef.current?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n  }, [formError]);\n  const [isSaving, setIsSaving] = React.useState(false);\n  const [pendingDeletion, setPendingDeletion] = React.useState<BeneficialOwner | null>(null);\n  const [isDeleting, setIsDeleting] = React.useState(false);\n  const [isEditingTaxId, setIsEditingTaxId] = React.useState(false);\n  const [useGovernmentIdForUs, setUseGovernmentIdForUs] = React.useState(false);\n  const uid = React.useId();\n\n  const refresh = React.useCallback(async () => {\n    setIsLoading(true);\n    setLoadError(null);\n    try {\n      const response = await request({\n        method: \"GET\",\n        url: Routes.settings_beneficial_owners_path(),\n        accept: \"json\",\n      });\n      if (!response.ok) throw new ResponseError(`Request failed (${response.status})`);\n      const data = typia.assert<{ beneficial_owners: BeneficialOwner[] }>(await response.json());\n      setOwners(data.beneficial_owners);\n    } catch (error) {\n      setLoadError(error instanceof Error ? error.message : \"Couldn't load beneficial owners.\");\n    } finally {\n      setIsLoading(false);\n    }\n  }, []);\n\n  React.useEffect(() => {\n    void refresh();\n  }, [refresh]);\n\n  const openCreate = () => {\n    setEditState({ mode: \"create\" });\n    setFormState(blankFormState(defaultCountry));\n    setFormError(null);\n    setIsEditingTaxId(true);","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/javascript/components/Settings/PaymentsPage/BeneficialOwnersSection.tsx#L440-L476","documentation":"Load-path error in the Stripe payouts 'beneficial owners' KYC section. The refresh() callback GETs Routes.settings_beneficial_owners_path expecting { beneficial_owners: [...] }; any non-2xx status throws ResponseError(`Request failed (${response.status})`) — a template literal, so the user sees the real status interpolated (e.g. 'Request failed (401)'). Network failures and JSON/typia mismatches instead produce 'Couldn't load beneficial owners.', so this exact message pinpoints an HTTP status problem rather than a parsing or transport one.","triggerScenarios":"GET /settings/beneficial_owners returns 401 (expired session), 403 (account not eligible for the payouts KYC flow), 404/419, or 500 — anything that makes response.ok false after the request completed.","commonSituations":"Session expiry while the payments page sat open, staging deploys where the route is missing, seller accounts that cannot access payouts KYC endpoints, or server-side exceptions in the beneficial owners controller.","solutions":["Read the status from the message itself — it is the response's actual HTTP code.","For 401/redirect: reload, re-authenticate, then reopen the Payments page section.","For 403: verify the account is eligible for the Stripe payouts KYC flow.","For 5xx: check Rails logs for the raised exception in the beneficial owners controller."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"const isNonOkJson = async (\n  response: Response,\n): Promise<{ ok: true } | { ok: false; status: number; body: unknown }> =>\n  response.ok ? { ok: true } : { ok: false, status: response.status, body: await response.json().catch(() => null) };","tryCatchPattern":"try {\n  const response = await request({ method: \"GET\", url: Routes.settings_beneficial_owners_path(), accept: \"json\" });\n  if (!response.ok) throw new ResponseError(`Request failed (${response.status})`);\n  const data = typia.assert<{ beneficial_owners: BeneficialOwner[] }>(await response.json());\n  setOwners(data.beneficial_owners);\n} catch (error) {\n  setLoadError(error instanceof Error ? error.message : \"Couldn't load beneficial owners.\");\n} finally {\n  setIsLoading(false);\n}","preventionTips":["Include the HTTP status in fallback messages (as this code does) so failures are diagnosable from a screenshot.","Handle 401 globally in the request() wrapper by redirecting to login.","Smoke-test KYC endpoints after route or feature-flag changes."],"tags":["payments","kyc","stripe-connect","http","settings"],"backgroundTag":"http-request-failed","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}