{"record":{"id":"44eac42475ba5a65","repo":"moeru-ai/airi","slug":"auth-request-failed-response-status","errorCode":null,"errorMessage":"Auth request failed (${response.status})","messagePattern":"Auth request failed \\((.+?)\\)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/ui-server-auth/src/modules/auth-fetch.ts","lineNumber":70,"sourceCode":"  const endpoint = new URL(`/api/auth${path}`, base.apiServerUrl)\n\n  const response = await fetchImpl(endpoint.toString(), {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify(body),\n    credentials: 'include',\n  })\n\n  let data: unknown\n  try {\n    data = await response.json()\n  }\n  catch {\n    data = null\n  }\n\n  if (!response.ok) {\n    throw new Error(extractAuthError(data) ?? `Auth request failed (${response.status})`)\n  }\n\n  return parse(data, response)\n}\n\n/**\n * GET `/api/auth<path>` and parse the response with `parse`.\n *\n * Use when:\n * - Reading a Better Auth GET endpoint (e.g. `/get-session`) from the UI and\n *   you want the same `credentials: include` + error-shape handling as\n *   {@link postAuthJSON}.\n *\n * Expects:\n * - `path` starts with a leading slash.\n * - `parse` runs only on 2xx responses; non-2xx throws with the server message.\n *\n * Returns:","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/apps/ui-server-auth/src/modules/auth-fetch.ts#L52-L88","documentation":"Thrown by postAuthJSON when a POST to /api/auth<path> returns a non-2xx status and the response body has no extractable Better Auth message field. The fallback string includes the HTTP status code. extractAuthError is tried first for data.message / data.error / data.error.message; only when none match does this generic message surface.","triggerScenarios":"POST /api/auth/sign-in/email with wrong credentials where the server returns a non-standard error shape; the auth server is unreachable and returns an HTML 502 with no JSON (data stays null); CORS/network error producing a 500 with empty body.","commonSituations":"Auth server (server/apps/auth) is down or misconfigured; a reverse proxy (Caddy) returns an error page instead of JSON; the API server URL is wrong (apiServerUrl points to the wrong origin); version mismatch between client and server changing the error envelope shape.","solutions":["Check response.status in the error context — 401 means bad credentials, 5xx means server/proxy fault.","Verify apiServerUrl points at the running auth service (dev: http://localhost:3000).","If the body is non-JSON, inspect the proxy/server logs; the generic message means extractAuthError found nothing.","Extend extractAuthError if the server returns a new error shape, so users see the real reason."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await postAuthJSON(base, '/sign-in/email', body, parse)\n} catch (e) {\n  const statusMatch = e.message.match(/\\((\\d+)\\)$/)\n  const status = statusMatch ? Number(statusMatch[1]) : null\n  if (status === 401) // invalid credentials\n  else if (status && status >= 500) // server/proxy fault, retry or surface\n}","preventionTips":["Confirm apiServerUrl points at the running auth service before deploy.","Keep extractAuthError updated when the server's error envelope shape changes.","Log response.status alongside the message for triage."],"tags":["auth","network","http","better-auth","ui-server-auth"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}