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

  1. Pass a file path: `node scripts/plan-canvas.js open .claude/plans/feature.plan.md`.
  2. Quote shell variables so an empty path is caught at the call site (`[ -n "$FILE" ] || exit 1`).
  3. 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

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


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/927895ce4495ff8f. Report an issue: GitHub.