{"record":{"id":"241e50e7b1bfe963","repo":"pbakaus/impeccable","slug":"status-failed-res-status-res-statustext","errorCode":null,"errorMessage":"Status failed: ${res.status} ${res.statusText}","messagePattern":"Status failed: (.+?) (.+?)","errorType":"exception","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/f88b2837a7d7c3182e46307bbbb091a1ed547571/skill/scripts/live-poll.mjs#L120-L156","documentation":"fetchServerStatus(base, token) in skill/scripts/live-poll.mjs issues GET ${base}/status?token=${token} against the Impeccable live server. A 401 is mapped first to AUTH_FAILED ('The server token may have changed.'), so this throw means the server answered HTTP but with a different non-OK status — 404, 500, 502, 504, etc. — and the message embeds the numeric status plus statusText for diagnosis.","triggerScenarios":"base points at the wrong port or includes a wrong path so an intermediary 404s; the live server hit an internal error (500) while handling /status; a reverse proxy/gateway in front of the server returns 502/504; a stale base from a previous server instance whose port now hosts a different service.","commonSituations":"The live server was restarted on a new port while the polling script kept the old base; another dev server (Vite/Astro) now occupies the port; corporate proxies or SSL-terminating fronts intercepting localhost requests.","solutions":["Confirm the live server is running and read the port it prints; rebuild base from it","Reproduce directly: curl \"${base}/status?token=${token}\" and inspect the status code and body","Check the live-server console for a stack trace when the status is 5xx","Remove any reverse proxy from the URL or fix its timeouts if it fronts the live server","If the status flips to 401/AUTH_FAILED, the server token changed — re-read the current token instead of retrying the old one"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"async function serverReachable(base, token) {\n  try {\n    const res = await fetch(`${base}/status?token=${token}`);\n    if (res.status === 401) return { ok: false, reason: 'AUTH_FAILED' };\n    return { ok: res.ok, reason: res.ok ? null : `HTTP ${res.status}` };\n  } catch (err) {\n    return { ok: false, reason: err.cause?.code || err.message }; // ECONNREFUSED etc.\n  }\n}\n\nconst probe = await serverReachable(base, token);\nif (!probe.ok) throw new Error(`live server not ready: ${probe.reason}`);","typeGuard":null,"tryCatchPattern":"for (let attempt = 1; attempt <= 3; attempt++) {\n  try {\n    status = await fetchServerStatus(base, token);\n    break;\n  } catch (err) {\n    if (err?.code === 'AUTH_FAILED') throw err; // token problem: retrying cannot help\n    const transient = /^Status failed: 5/.test(err?.message || '');\n    if (!transient || attempt === 3) throw err;\n    await backoff(attempt);\n  }\n}","preventionTips":["Derive base from the port the live server prints at boot; never hardcode a stale one","Distinguish 401/AUTH_FAILED (re-read the token) from 5xx (check server logs) before any retry","Keep reverse proxies off the localhost live-server path or raise their timeouts"],"tags":["http","live-server","network","status"],"backgroundTag":"http-error-response","analyzedSha":"f88b2837a7d7c3182e46307bbbb091a1ed547571","analyzedAt":"2026-08-18T04:58:36.608Z","contentChangedAt":"2026-08-18T04:58:36.608Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}