affaan-m/ECC · error · Error

open requires a file path

Error message

open requires a file path

What it means

cmdOpen validates its inputs before touching the server: the first argument must be a file path. When invoked without a file (e.g. `plan-canvas open` with no operand), it throws this error instead of sending a malformed session-creation request.

Solutions

  1. Pass the plan/artifact path: `node scripts/plan-canvas.js open <path-to-file>`.
  2. Check the invoking script for an empty/unset variable holding the file path.
  3. Confirm you are using the right subcommand — `status` doesn't need a file, `open` does.
  4. Shell-quote the path so spaces don't split it into separate arguments.

Example fix

// before
FILE="" ; node scripts/plan-canvas.js open "$FILE"
// after
FILE="docs/plan.html" ; node scripts/plan-canvas.js open "$FILE"
Defensive patterns

Strategy: validation

Validate before calling

const file = process.argv[3];
if (!file) {
  console.error('Usage: plan-canvas open <file>');
  process.exit(2);
}
if (!fs.existsSync(path.resolve(file))) {
  console.error(`artifact not found: ${file}`);
  process.exit(2);
}

Type guard

function hasFileArg(v) { return typeof v === 'string' && v.trim().length > 0; }

Try / catch

try {
  await cmdOpen(file, args, { stateDir, port });
} catch (err) {
  if (err.message === 'open requires a file path') {
    console.error('Usage: node scripts/plan-canvas.js open <file>');
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: Running `node scripts/plan-canvas.js open` with no path argument; a wrapper script dropping its argument due to quoting (`open "$FILE"` with FILE empty); dispatching cmdOpen programmatically with undefined as the file parameter.

Common situations: CI jobs where the plan file variable is unset; shell aliases forgetting the argument; confusion between subcommands where `status` takes no file but `open` does.

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


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/927895ce4495ff8f. Report an issue: GitHub.

Appendix: 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 8321021c54)