{"record":{"id":"6d6662f0dcd64635","repo":"affaan-m/ECC","slug":"await-requires-a-file-path","errorCode":null,"errorMessage":"await requires a file path","messagePattern":"await requires a file path","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/plan-canvas.js","lineNumber":273,"sourceCode":"          data += chunk;\n        });\n        res.on('end', () => {\n          try {\n            resolve(JSON.parse(data.trim()));\n          } catch {\n            reject(new Error('await response was not JSON (server restarted?) - re-run await; feedback is never lost'));\n          }\n        });\n      }\n    );\n    req.setTimeout(0);\n    req.on('error', reject);\n    req.end();\n  });\n}\n\nasync function cmdAwait(file, args, { stateDir, port }) {\n  if (!file) throw new Error('await requires a file path');\n  if (!(await healthCheck(port))) {\n    return { status: 'no-server', hint: 'no canvas server is running; use `open` first', stateDir };\n  }\n  const reply = valueAfter(args, '--reply');\n  if (reply) {\n    const key = sessionKeyFor(canonicalizeArtifactPath(file));\n    await request(port, 'POST', `/api/session/${key}/reply`, { text: reply });\n  }\n  const timeoutRaw = valueAfter(args, '--timeout-ms');\n  const timeoutMs = timeoutRaw === null ? null : Number.parseInt(timeoutRaw, 10) || 0;\n  process.stderr.write('[plan-canvas] waiting for human feedback... leave this running (re-run if interrupted; queued feedback is never lost)\\n');\n  const result = await awaitRequest(port, sessionKeyFor(canonicalizeArtifactPath(file)), timeoutMs);\n  if (result.status === 'feedback') {\n    result.next_step = result.sessionEnded\n      ? 'The user sent this feedback and ended the session. Address it and report in chat; do not reopen the canvas uninvited.'\n      : 'Address the feedback, then run `ecc-plan-canvas await <file> --reply \"<what you changed>\"` to answer in the canvas and keep listening.';\n  } else if (result.status === 'ended') {\n    result.next_step =","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/plan-canvas.js#L255-L291","documentation":"Thrown by cmdAwait in the Plan Canvas CLI when the `await` subcommand is invoked without a positional file argument. The await command long-polls the local canvas server for human feedback on a specific plan/artifact, so it must know which file's review session to wait on. Without a file there is no session key to bind the poll to.","triggerScenarios":"Running `node scripts/plan-canvas.js await` with no positional arg; passing only flags like `--reply` or `--timeout-ms` but no file path first; a wrapper script that interpolates an empty/undefined file variable.","commonSituations":"Agent harness invokes plan-canvas with a variable that resolved to empty; user forgets the file after copying a flag-only example; CI runs `await` against a glob that matched nothing.","solutions":["Pass the plan/artifact file as the first positional argument: `node scripts/plan-canvas.js await .claude/plans/feature.plan.md`.","If wrapping the call in a script, guard the file variable before invoking: `if [ -z \"$FILE\" ]; then exit 1; fi`.","Run `node scripts/plan-canvas.js` with no args (or --help) to see the usage block listing required positional args per subcommand."],"exampleFix":"// before\nnode scripts/plan-canvas.js await --reply \"done\"\n// after\nnode scripts/plan-canvas.js await .claude/plans/feature.plan.md --reply \"done\"","handlingStrategy":"validation","validationCode":"// Before calling cmdAwait, ensure file is a non-empty string\nfunction validateAwaitArgs(file) {\n  if (typeof file !== 'string' || file.trim() === '') {\n    throw new Error('cmdAwait: file argument is required (e.g. .claude/plans/feature.plan.md)');\n  }\n  return file;\n}","typeGuard":"// Narrow a CLI positional to a valid await file\nfunction isAwaitFile(arg) {\n  return typeof arg === 'string' && arg.length > 0 && !arg.startsWith('--');\n}","tryCatchPattern":"// Wrap the subcommand dispatch so a missing-file usage error surfaces as a clean exit\ntry {\n  await cmdAwait(file, args, ctx);\n} catch (err) {\n  if (err.message === 'await requires a file path') {\n    console.error('Usage: node scripts/plan-canvas.js await <file> [--reply text] [--timeout-ms n]');\n    process.exit(2);\n  }\n  throw err;\n}","preventionTips":["Always pass the plan file as the first positional after the `await` subcommand.","In agent harnesses, assert the file variable is set before invoking plan-canvas.","Keep a list of open files in the orchestrator so await/end always reference a real path."],"tags":["cli","argument-validation","plan-canvas"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}