affaan-m/ECC · error · Error
open requires a file path
Error message
open requires a file path
What it means
Thrown by cmdOpen in scripts/plan-canvas.js when the `open` subcommand is invoked with no file path argument. The first positional arg is the artifact file to open in the review canvas; omitting it is rejected before any server interaction. (A non-existent but supplied path hits a separate 'artifact not found' error.)
Source
Thrown at scripts/plan-canvas.js:225
return false;
}
}
function output(payload) {
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
}
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.'
};
}View on GitHub (pinned to 01e15490f0)
Solutions
- Pass a file path: `node scripts/plan-canvas.js open .claude/plans/feature.plan.md`.
- Quote shell variables so an empty path is caught at the call site (`[ -n "$FILE" ] || exit 1`).
- Use an absolute or repo-relative path; the command resolves it with path.resolve.
Example fix
// before node scripts/plan-canvas.js open --no-open // after node scripts/plan-canvas.js open .claude/plans/feature.plan.md --no-open
Defensive patterns
Strategy: validation
Validate before calling
function assertFileArg(file) {
if (typeof file !== 'string' || file.length === 0) {
throw new Error('open requires a non-empty file path');
}
return file;
} Type guard
function isNonEmptyString(value) {
return typeof value === 'string' && value.length > 0;
} Prevention
- Quote shell variables holding the path so empty expansions are caught early.
- In wrappers, assert the file exists before invoking `open` to get a clearer error.
- Treat a missing path as a configuration failure, not a runtime retry.
When it happens
Trigger: Running `node scripts/plan-canvas.js open` with no trailing file, or with only flags (`open --no-open`). The file is read from args[0] after the command is shifted off; if it is undefined, this throws.
Common situations: A wrapper script that conditionally includes the file path; a shell variable for the path that expanded to empty; copy-pasting the usage line and forgetting to substitute a real path.
Related errors
- await requires a file path
- typing requires a file path
- end requires a file path
- Unknown argument: ${arg}
- Unknown argument: ${arg}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/927895ce4495ff8f.
Report an issue: GitHub.