{"record":{"id":"413574c839d9ead9","repo":"affaan-m/ECC","slug":"open-failed-http-res-statuscode","errorCode":null,"errorMessage":"open failed (HTTP ${res.statusCode})","messagePattern":"open failed \\(HTTP (.+?)\\)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/plan-canvas.js","lineNumber":233,"sourceCode":"async function cmdStatus({ stateDir, port }) {\n  const health = await healthCheck(port);\n  if (!health) {\n    return { server: 'not running', hint: 'open an artifact to start one', stateDir };\n  }\n  const sessions = await request(port, 'GET', '/api/sessions');\n  return { server: `http://${DEFAULT_HOST}:${port}`, version: health.version, sessions: sessions.body.sessions };\n}\n\nasync function cmdOpen(file, args, { stateDir, port }) {\n  if (!file) throw new Error('open requires a file path');\n  if (!fs.existsSync(path.resolve(file))) throw new Error(`artifact not found: ${file}`);\n  await ensureServer({ stateDir, port });\n  const res = await request(port, 'POST', '/api/sessions', {\n    file: path.resolve(file),\n    reopen: args.includes('--reopen')\n  });\n  if (res.statusCode === 409) return res.body;\n  if (res.statusCode !== 200) throw new Error(res.body.error || `open failed (HTTP ${res.statusCode})`);\n  const url = `http://${DEFAULT_HOST}:${port}${res.body.url}`;\n  const launched = args.includes('--no-open') ? false : openBrowser(url);\n  return {\n    status: 'open',\n    url,\n    browser: launched ? 'opened' : 'not opened',\n    next_step:\n      'Run `ecc-plan-canvas await <file>` and leave it running; it returns when the human sends feedback, a verdict, or ends the session.'\n  };\n}\n\nfunction awaitRequest(port, key, timeoutMs) {\n  if (!/^[a-f0-9]{12}$/.test(key)) throw new Error('invalid plan-canvas session key');\n  const params = new URLSearchParams({ key });\n  if (timeoutMs !== null) params.set('timeoutMs', String(timeoutMs));\n  return new Promise((resolve, reject) => {\n    const req = http.request(\n      requestOptions(port, 'GET', `/api/await?${params}`, {}),","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/plan-canvas.js#L215-L251","documentation":"cmdOpen in the plan-canvas CLI opens (or reopens) a canvas session by POSTing the file path to the local canvas server. The server is expected to answer 200 on success or 409 when the session is already open (in which case the body is returned as-is). Any other HTTP status means the server rejected the request, and since the error body carried no message, the CLI surfaces a generic `open failed (HTTP <status>)` error.","triggerScenarios":"Running `ecc-plan-canvas open <file>` when the server responds with a status other than 200 or 409 — e.g. 400 for an invalid/missing file path, 404 when the resolved file does not exist, 500 on a server-side failure writing session state, or 502/503 if a proxy intercepts the localhost request. It also fires when `res.body` is not the expected JSON envelope so `res.body.error` is undefined.","commonSituations":"Passing a relative or mistyped file path so path.resolve points at a nonexistent artifact; the canvas server crashed or is a stale process from a previous version that no longer understands the POST /api/sessions payload; port contention causing the request to hit a different service; a corporate proxy intercepting localhost HTTP traffic.","solutions":["Check that the file path passed to `open` exists and is correct (run `ls` on the resolved path) — most non-200/409 statuses come from the server rejecting the path.","Look at the server logs or state dir for the real error body; rerun with the server in the foreground to see why /api/sessions rejected the request.","If the server version is stale (e.g. after upgrading ECC), stop it with `ecc-plan-canvas stop` and reopen so a current server process handles the request.","Verify nothing else is bound to the port (lsof/netstat) and that no proxy env vars (HTTP_PROXY) intercept 127.0.0.1; unset them or add a NO_PROXY for localhost.","Retry after fixing; if the response body included an error field, the CLI would have shown that message instead — treat the bare status code as a signal the body was unexpected and inspect raw traffic."],"exampleFix":"// before (path may not exist, server 404s)\nawait ensureServer({ stateDir, port });\nconst res = await request(port, 'POST', '/api/sessions', { file: path.resolve(file) });\n\n// after (validate before calling)\nconst resolved = path.resolve(file);\nif (!fs.existsSync(resolved)) {\n  throw new Error(`plan file not found: ${resolved}`);\n}\nconst res = await request(port, 'POST', '/api/sessions', { file: resolved });","handlingStrategy":"try-catch","validationCode":"const resolved = path.resolve(file);\nif (!fs.existsSync(resolved)) throw new Error(`plan file not found: ${resolved}`);\nif (!(await healthCheck(port))) throw new Error('canvas server not running');","typeGuard":null,"tryCatchPattern":"try {\n  const res = await request(port, 'POST', '/api/sessions', { file: resolved });\n  if (res.statusCode !== 200 && res.statusCode !== 409) {\n    throw new Error(res.body?.error || `open failed (HTTP ${res.statusCode})`);\n  }\n} catch (err) {\n  console.error('open failed:', err.message);\n  // inspect server logs; consider `ecc-plan-canvas stop` and reopen\n}","preventionTips":["Always verify the plan file exists before calling open.","Restart the canvas server after ECC upgrades so client and server routes match.","Set NO_PROXY=localhost so proxies don't intercept the local API call.","Prefer error bodies (res.body.error) in your own logging to preserve the server's reason."],"tags":["http","cli","local-server","plan-canvas"],"backgroundTag":"http-error-response","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}