{"record":{"id":"241e50e7b1bfe963","repo":"pbakaus/impeccable","slug":"status-failed-res-status-res-statustext-241e50","errorCode":null,"errorMessage":"Status failed: ${res.status} ${res.statusText}","messagePattern":"Status failed: (.+?) (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skill/scripts/live-poll.mjs","lineNumber":138,"sourceCode":"  if (!res.ok) {\n    const body = await res.json().catch(() => ({}));\n    const failureLines = Array.isArray(body.failures)\n      ? body.failures.map((f) => `  ${f.file}${f.line != null ? `:${f.line}` : ''} ${f.message}`).join('\\n')\n      : null;\n    const parts = [body.error || res.statusText, body.reason, body.hint, failureLines, body._instructions].filter(Boolean);\n    throw new Error(parts.join('\\n'));\n  }\n}\n\nexport async function fetchServerStatus(base, token) {\n  const res = await fetch(`${base}/status?token=${token}`);\n  if (res.status === 401) {\n    const err = new Error('Authentication failed. The server token may have changed.');\n    err.code = 'AUTH_FAILED';\n    throw err;\n  }\n  if (!res.ok) {\n    throw new Error(`Status failed: ${res.status} ${res.statusText}`);\n  }\n  return res.json();\n}\n\nexport function isEventPending(status, eventId) {\n  return (status.pendingEvents || []).some((entry) => entry.id === eventId);\n}\n\nexport async function waitForEventAck(base, token, eventId, {\n  pollIntervalMs = 400,\n  maxWaitMs = 600_000,\n} = {}) {\n  const deadline = Date.now() + maxWaitMs;\n  while (Date.now() < deadline) {\n    const status = await fetchServerStatus(base, token);\n    if (!isEventPending(status, eventId)) return true;\n    await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n  }","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/pbakaus/impeccable/blob/d14711ae3d1a1dd62dee61a358d27f107c51ccd0/skill/scripts/live-poll.mjs#L120-L156","documentation":"Thrown by fetchServerStatus() in live-poll.mjs when GET {base}/status?token=... returns a non-OK status other than 401. A 401 is handled separately with an AUTH_FAILED error code; every other failure (5xx, 404, 403) collapses to this generic message carrying the numeric status and statusText. The function returns res.json() on success, so any non-JSON or error response aborts the status handshake.","triggerScenarios":"fetchServerStatus(base, token) is invoked (by waitForEventAck, the live agent loop, or a manual health check) and the server responds with e.g. 500 Internal Server Error, 502 Bad Gateway, 404 (wrong base URL), or 403. A 401 would have thrown 'Authentication failed' with code AUTH_FAILED instead.","commonSituations":"Live server crashed or is restarting (5xx); base URL is wrong/proxied and hits a different service (404); reverse proxy or Cloudflare Pages Functions returned an error page; server version mismatch where /status route was renamed; port confusion pointing at a different dev server.","solutions":["Confirm the base URL and port point at the Impeccable Live server (not the app dev server or a proxy).","Check the server process is alive and inspect its logs for the matching status code.","If 401-style but reported as 403, verify the token matches the one the server booted with.","Retry once the server is healthy; persistent 5xx indicates a server bug to file."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Cheap preflight before the status handshake.\nasync function isReachable(base) {\n  try { const r = await fetch(base, { method: 'HEAD' }); return r.ok || r.status < 500; } catch { return false; }\n}\nif (!(await isReachable(base))) throw new Error('live server unreachable at ' + base);","typeGuard":null,"tryCatchPattern":"try {\n  const status = await fetchServerStatus(base, token);\n} catch (err) {\n  if (err.code === 'AUTH_FAILED') throw err; // re-raise auth, handled elsewhere\n  // transient server error — back off and retry with jitter\n  console.warn('status fetch failed:', err.message);\n  throw err;\n}","preventionTips":["Keep the base URL in a single config source to avoid pointing at the wrong server.","Add a health check (GET /status) at agent startup before entering the poll loop.","Distinguish 401 (auth) from other statuses; only retry transient 5xx with backoff."],"tags":["network","live-poll","server-error","http","status"],"backgroundTag":null,"analyzedSha":"d14711ae3d1a1dd62dee61a358d27f107c51ccd0","analyzedAt":"2026-08-13T00:52:25.771Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}