{"record":{"id":"67acbbfaf319868d","repo":"affaan-m/ECC","slug":"http-res-status","errorCode":null,"errorMessage":"HTTP ${res.status}","messagePattern":"HTTP \\$\\{res\\.status\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"scripts/lib/plan-canvas/ui.js","lineNumber":385,"sourceCode":"    if (ended || sending) return;\n    const items = queue.slice();\n    if (extraItems) items.push(...extraItems);\n    const text = input.value.trim();\n    if (text) items.push({ kind: 'chat', text });\n    if (!items.length) {\n      statusEl.textContent = 'Nothing to send yet - annotate the plan or type a message.';\n      return;\n    }\n    sending = true;\n    sendBtn.disabled = true;\n    statusEl.textContent = 'Sending\\\\u2026';\n    try {\n      const res = await fetch('/api/session/' + key + '/feedback', {\n        method: 'POST',\n        headers: { 'content-type': 'application/json' },\n        body: JSON.stringify({ items })\n      });\n      if (!res.ok) throw new Error('HTTP ' + res.status);\n      const body = await res.json().catch(() => ({}));\n      queue = [];\n      persistQueue();\n      renderQueue();\n      input.value = '';\n      // Say what actually happened: a parked agent takes the batch on the\n      // spot, otherwise it sits in the queue until the agent checks in.\n      statusEl.textContent = body.presence === 'thinking' || body.presence === 'typing'\n        ? 'Delivered. Your agent has it.'\n        : 'Queued. Your agent picks this up the moment it checks in.';\n      if (body.presence) applyPresence(body.presence);\n    } catch (err) {\n      statusEl.textContent = 'Send failed (' + err.message + ') - is the canvas server still running?';\n    } finally {\n      sending = false;\n      sendBtn.disabled = ended;\n    }\n  }","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/plan-canvas/ui.js#L367-L403","documentation":"Thrown inside the plan-canvas browser UI's send() function when the POST to /api/session/{key}/feedback returns a non-2xx HTTP status. The fetch promise resolves but res.ok is false, so the client throws to surface the status code. The catch handler then shows a 'Send failed' message to the reviewer.","triggerScenarios":"The plan-canvas server returns 400 (malformed items), 404 (unknown session key), 409 (session ended), or 500 (server error); the server process restarted and lost in-memory session state; a proxy/gateway between browser and server returns a 502/503.","commonSituations":"The agent ended the session server-side but the browser tab was still open; the canvas server was killed and relaunched; a long-idle review tab whose session expired; the feedback payload shape changed across versions and the server rejects it.","solutions":["Check the plan-canvas server is still running and the session key is still valid.","Reload the canvas page to obtain a fresh session key from the server boot payload.","Inspect the server logs for the non-2xx cause; retry the send once the server is healthy.","If the session ended, start a new review session rather than retrying the dead one."],"exampleFix":"// before (client side)\nif (!res.ok) throw new Error('HTTP ' + res.status); // bare status, no body\n\n// after (client side) — include server detail for diagnostics\nif (!res.ok) {\n  const detail = await res.text().catch(() => '');\n  throw new Error(`HTTP ${res.status}: ${detail || res.statusText}`);\n}","handlingStrategy":"retry","validationCode":"// Browser-side preflight: confirm session is live before sending.\nconst probe = await fetch('/api/session/' + key).catch(() => null);\nif (!probe || !probe.ok) {\n  statusEl.textContent = 'Session unavailable. Reload to get a new key.';\n  return;\n}\n// then proceed with the POST","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch('/api/session/' + key + '/feedback', {...});\n  if (!res.ok) throw new Error('HTTP ' + res.status);\n  // ...\n} catch (err) {\n  statusEl.textContent = 'Send failed (' + err.message + ') - is the canvas server still running?';\n  // offer a reload; do not infinite-retry a dead session\n}","preventionTips":["Reload the canvas page if the session key may be stale.","Confirm the plan-canvas server process is alive before long review sessions.","Start a new session rather than retrying an ended one."],"tags":["network","plan-canvas","http","browser"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}