affaan-m/ECC · error · Error
open failed (HTTP ${res.statusCode})
Error message
open failed (HTTP ${res.statusCode}) What it means
Thrown by cmdOpen in scripts/plan-canvas.js when POST /api/sessions returns a status code that is neither 200 (success) nor 409 (conflict, session already open). The message prefers the server's own error body if present, falling back to the generic HTTP-status form shown. This indicates the canvas server received the request but rejected it.
Source
Thrown at scripts/plan-canvas.js:233
async function cmdStatus({ stateDir, port }) {
const health = await healthCheck(port);
if (!health) {
return { server: 'not running', hint: 'open an artifact to start one', stateDir };
}
const sessions = await request(port, 'GET', '/api/sessions');
return { server: `http://${DEFAULT_HOST}:${port}`, version: health.version, sessions: sessions.body.sessions };
}
async function cmdOpen(file, args, { stateDir, port }) {
if (!file) throw new Error('open requires a file path');
if (!fs.existsSync(path.resolve(file))) throw new Error(`artifact not found: ${file}`);
await ensureServer({ stateDir, port });
const res = await request(port, 'POST', '/api/sessions', {
file: path.resolve(file),
reopen: args.includes('--reopen')
});
if (res.statusCode === 409) return res.body;
if (res.statusCode !== 200) throw new Error(res.body.error || `open failed (HTTP ${res.statusCode})`);
const url = `http://${DEFAULT_HOST}:${port}${res.body.url}`;
const launched = args.includes('--no-open') ? false : openBrowser(url);
return {
status: 'open',
url,
browser: launched ? 'opened' : 'not opened',
next_step:
'Run `ecc-plan-canvas await <file>` and leave it running; it returns when the human sends feedback, a verdict, or ends the session.'
};
}
function awaitRequest(port, key, timeoutMs) {
if (!/^[a-f0-9]{12}$/.test(key)) throw new Error('invalid plan-canvas session key');
const params = new URLSearchParams({ key });
if (timeoutMs !== null) params.set('timeoutMs', String(timeoutMs));
return new Promise((resolve, reject) => {
const req = http.request(
requestOptions(port, 'GET', `/api/await?${params}`, {}),View on GitHub (pinned to 01e15490f0)
Solutions
- If res.body.error was surfaced, address that specific message first.
- Restart the server (`node scripts/plan-canvas.js stop`, then retry open) to clear transient state.
- Inspect server.log in the state directory for the stack trace behind a 500.
- Ensure the ECC version of the running server matches the CLI (a version mismatch normally triggers a clean restart, but a stale server.json can defeat that).
Defensive patterns
Strategy: try-catch
Try / catch
try {
return await cmdOpen(file, args, context);
} catch (err) {
if (/open failed \(HTTP/.test(err.message)) {
const log = fs.readFileSync(path.join(stateDir, 'server.log'), 'utf8');
console.error('Session creation failed. server.log tail:\n', log.split('\n').slice(-30).join('\n'));
await cmdStop(context); // reset before retry
}
throw err;
} Prevention
- Always read server.log when a non-200/409 is returned — the server-side error is logged there.
- Stop and restart the canvas server between retries to clear corrupted session state.
- Confirm the running server version matches the CLI before assuming a protocol error.
When it happens
Trigger: The server returns 400 (malformed session body), 500 (internal error during session creation), or any other non-200/409 code. If res.body.error is set by the server, that message is used; otherwise the generic `open failed (HTTP <code>)` is thrown.
Common situations: The artifact file watcher cannot read the file at session-creation time; the session store on disk is corrupted; a server bug during canonicalization; a version-skewed server that does not understand the request shape.
Related errors
- HTTP ${res.status}
- plan-canvas server did not become healthy on port ${port}; c
- Unexpected EOF while reading HTTP request
- HTTP request headers too large
- invalid plan-canvas server port: ${port}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/413574c839d9ead9.
Report an issue: GitHub.