{"record":{"id":"cde941bd5c3575c9","repo":"unslothai/unsloth","slug":"parseerrortext-response-status-body-cde941","errorCode":null,"errorMessage":"${parseErrorText(response.status, body)}","messagePattern":"\\$\\{parseErrorText\\(response\\.status, body\\)\\}","errorType":"http","errorClass":"ChatSettingsRequestError","httpStatus":null,"severity":"error","filePath":"studio/frontend/src/features/chat/api/chat-settings-api.ts","lineNumber":109,"sourceCode":"  }\n  if (\n    body &&\n    typeof body === \"object\" &&\n    \"message\" in body &&\n    typeof body.message === \"string\"\n  ) {\n    return body.message;\n  }\n  return `Request failed (${status})`;\n}\n\nasync function parseJsonOrThrow<T>(response: Response): Promise<T> {\n  const body = await response.json().catch(() => null);\n  if (!response.ok) {\n    // Typed, not a bare Error: the settings queue has to tell a server that is\n    // down (keep the patch) from a server that refuses this body (drop the\n    // offending fields), and that decision needs the status and the detail.\n    throw new ChatSettingsRequestError(\n      parseErrorText(response.status, body),\n      response.status,\n      body && typeof body === \"object\" && \"detail\" in body\n        ? (body as { detail: unknown }).detail\n        : null,\n    );\n  }\n  return body as T;\n}\n\nexport async function getChatSettings(): Promise<PersistedChatSettings> {\n  const response = await authFetch(\"/api/chat/settings\");\n  const data = await parseJsonOrThrow<ChatSettingsResponse>(response);\n  return data.settings;\n}\n\nexport async function saveChatSettingsPatch(\n  patch: PersistedChatSettings,","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/frontend/src/features/chat/api/chat-settings-api.ts#L91-L127","documentation":"ChatSettingsRequestError (defined in settings-retry.ts) is thrown by parseJsonOrThrow in chat-settings-api.ts whenever a settings request returns non-2xx. Unlike a bare Error it carries response.status and the parsed detail, because the settings queue must distinguish 'server down' (keep the patch and retry later) from 'server rejects this body' (drop the offending fields). The message string itself is built by parseErrorText.","triggerScenarios":"Any failed GET/PUT of /api/chat/settings: server unreachable or 5xx (patch is kept for retry), or 422 with a detail describing which settings fields are invalid (fields get dropped).","commonSituations":"Backend restarted with a newer/older settings schema so stored client settings no longer validate; server briefly down while the queue flushes; auth expiry mid-sync.","solutions":["Handle the typed error: on 5xx/network statuses keep the patch queued and retry; on 422 read .detail and strip the rejected fields.","If schema drift caused 422s, re-fetch settings and reconcile with the fresh server shape.","Check the server is running for persistent 5xx."],"exampleFix":"// before\ncatch (e) { /* cannot tell down from refused */ }\n\n// after\nimport { ChatSettingsRequestError } from '../utils/settings-retry';\ncatch (e) {\n  if (e instanceof ChatSettingsRequestError) {\n    if (e.status >= 500 || e.status === 0) queueForRetry(patch);\n    else dropFieldsNamedIn(e.detail);\n  }\n}","handlingStrategy":"retry","validationCode":"// Pre-sync reconciliation: fetch server settings before pushing a patch\nconst server = await getChatSettings();\npatch = intersectKeys(patch, server); // drop fields the server no longer knows","typeGuard":"import { ChatSettingsRequestError } from '../utils/settings-retry';\nexport function isChatSettingsRequestError(e: unknown): e is ChatSettingsRequestError {\n  return e instanceof ChatSettingsRequestError;\n}","tryCatchPattern":"try { await pushSettings(patch); }\ncatch (e) {\n  if (!isChatSettingsRequestError(e)) throw e;\n  if (e.status >= 500) queuePatchForRetry(patch);   // server down: keep\n  else dropFieldsInDetail(patch, e.detail);          // refused: prune\n}","preventionTips":["Always branch on .status, never on message text, for queue decisions.","Re-fetch settings after backend upgrades to detect schema drift.","Cap the retry queue and surface persistent failure to the user."],"tags":["settings","retry-queue","http","schema-drift"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}