affaan-m/ECC · warning · Error
HTTP ${res.status}
Error message
HTTP ${res.status} What it means
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.
Source
Thrown at scripts/lib/plan-canvas/ui.js:385
if (ended || sending) return;
const items = queue.slice();
if (extraItems) items.push(...extraItems);
const text = input.value.trim();
if (text) items.push({ kind: 'chat', text });
if (!items.length) {
statusEl.textContent = 'Nothing to send yet - annotate the plan or type a message.';
return;
}
sending = true;
sendBtn.disabled = true;
statusEl.textContent = 'Sending\\u2026';
try {
const res = await fetch('/api/session/' + key + '/feedback', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ items })
});
if (!res.ok) throw new Error('HTTP ' + res.status);
const body = await res.json().catch(() => ({}));
queue = [];
persistQueue();
renderQueue();
input.value = '';
// Say what actually happened: a parked agent takes the batch on the
// spot, otherwise it sits in the queue until the agent checks in.
statusEl.textContent = body.presence === 'thinking' || body.presence === 'typing'
? 'Delivered. Your agent has it.'
: 'Queued. Your agent picks this up the moment it checks in.';
if (body.presence) applyPresence(body.presence);
} catch (err) {
statusEl.textContent = 'Send failed (' + err.message + ') - is the canvas server still running?';
} finally {
sending = false;
sendBtn.disabled = ended;
}
}View on GitHub (pinned to 01e15490f0)
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.
Example fix
// before (client side)
if (!res.ok) throw new Error('HTTP ' + res.status); // bare status, no body
// after (client side) — include server detail for diagnostics
if (!res.ok) {
const detail = await res.text().catch(() => '');
throw new Error(`HTTP ${res.status}: ${detail || res.statusText}`);
} Defensive patterns
Strategy: retry
Validate before calling
// Browser-side preflight: confirm session is live before sending.
const probe = await fetch('/api/session/' + key).catch(() => null);
if (!probe || !probe.ok) {
statusEl.textContent = 'Session unavailable. Reload to get a new key.';
return;
}
// then proceed with the POST Try / catch
try {
const res = await fetch('/api/session/' + key + '/feedback', {...});
if (!res.ok) throw new Error('HTTP ' + res.status);
// ...
} catch (err) {
statusEl.textContent = 'Send failed (' + err.message + ') - is the canvas server still running?';
// offer a reload; do not infinite-retry a dead session
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- open failed (HTTP ${res.statusCode})
- invalid plan-canvas server port: ${port}
- plan-canvas request path must be root-relative
- plan-canvas request path must stay on the loopback server
- unsupported plan-canvas request path: ${url.pathname}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/67acbbfaf319868d.
Report an issue: GitHub.