affaan-m/ECC · error · Error
end requires a file path
Error message
end requires a file path
What it means
cmdEnd terminates the canvas session tied to a plan file by POSTing the resolved path to /api/end. The file argument is mandatory; without it the command cannot identify which session to end and throws 'end requires a file path' immediately, before the health check.
Solutions
- Pass the plan file path: `ecc-plan-canvas end path/to/plan.md` (same path used with `open`).
- Guard shell variables: `: "${PLAN_FILE:?PLAN_FILE not set}"` before invoking end.
- If the session is already gone, note cmdEnd returns the server's body regardless — once a valid path is supplied, 'no-server' or an already-ended status is a non-error outcome.
- Fix any wrapper script so positional arguments are forwarded.
Example fix
# before ecc-plan-canvas end # after ecc-plan-canvas end "$PLAN_FILE" # e.g. ecc-plan-canvas end docs/plans/feature.plan.md
Defensive patterns
Strategy: validation
Validate before calling
if (!PLAN_FILE) { echo 'usage: ecc-plan-canvas end <file>' >&2; exit 2; } Prevention
- Reuse one canonical plan-path variable across open/await/end in CI cleanup steps.
- Fail fast on empty variables with :? expansions.
- Remember end is idempotent once a valid path is given — a 'no-server' body is fine.
When it happens
Trigger: Running `ecc-plan-canvas end` with no positional argument — omitted path, empty shell variable, or an npm-script/alias wrapper that does not forward arguments.
Common situations: Cleanup steps in CI where `END_FILE=$PLAN_FILE` was never set; ending a session from a different directory and assuming the tool infers 'the current plan'; typos where the path was given to the wrong flag.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- await requires a file path
- typing requires a file path
- An executable is required after --.
- An install config path is required
- At least one --target is required for handoffs.
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/338010ee18720f92.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/plan-canvas.js:329
// Report feedback the human sent that no agent has picked up yet. Reads state
// directly so it answers even when the server has idled out.
function cmdPending({ stateDir }) {
const store = createSessionStore({ stateDir });
const waiting = store
.list()
.filter(session => session.status !== 'ended' && session.pending > 0)
.map(session => ({ file: session.file, pending: session.pending, updatedAt: session.updatedAt }));
return {
status: waiting.length ? 'pending' : 'clear',
sessions: waiting,
next_step: waiting.length
? 'Run `ecc-plan-canvas await <file>` for each file above to receive the messages.'
: 'No canvas feedback is waiting.'
};
}
async function cmdEnd(file, { port }) {
if (!file) throw new Error('end requires a file path');
if (!(await healthCheck(port))) return { status: 'no-server' };
const res = await request(port, 'POST', '/api/end', { file: path.resolve(file) });
return res.body;
}
async function cmdStop({ stateDir, port }) {
if (!(await healthCheck(port))) return { status: 'not running' };
await request(port, 'POST', '/shutdown').catch(() => {});
fs.rmSync(serverInfoPath(stateDir), { force: true });
return { status: 'stopping' };
}
async function cmdServer(args, { stateDir, port }) {
const portArg = valueAfter(args, '--port');
const hostArg = valueAfter(args, '--host');
const listenPort = portArg !== null ? Number.parseInt(portArg, 10) : port;
const store = createSessionStore({ stateDir });
let shuttingDown = false;View on GitHub (pinned to 8321021c54)