affaan-m/ECC · error · Error

invalid plan-canvas server port: ${port}

Error message

invalid plan-canvas server port: ${port}

What it means

Thrown by validatePort in scripts/plan-canvas.js when the supplied port is not an integer in the range 0-65535. validatePort is called from requestOptions on every outbound HTTP request to the canvas server, so a bad port from server.json, the environment (ECC_PLAN_CANVAS_PORT), or the --port flag triggers it.

Source

Thrown at scripts/plan-canvas.js:96

  return index >= 0 && index + 1 < args.length ? args[index + 1] : null;
}

function serverInfoPath(stateDir) {
  return path.join(stateDir, 'server.json');
}

function readServerInfo(stateDir) {
  try {
    return JSON.parse(fs.readFileSync(serverInfoPath(stateDir), 'utf8'));
  } catch {
    return null;
  }
}

function validatePort(port) {
  const value = Number(port);
  if (!Number.isInteger(value) || value < 0 || value > 65535) {
    throw new Error(`invalid plan-canvas server port: ${port}`);
  }
  return value;
}

function validateRequestPath(requestPath) {
  if (typeof requestPath !== 'string' || !requestPath.startsWith('/')) {
    throw new Error('plan-canvas request path must be root-relative');
  }
  const url = new URL(requestPath, `http://${DEFAULT_HOST}`);
  if (url.hostname !== DEFAULT_HOST) {
    throw new Error('plan-canvas request path must stay on the loopback server');
  }
  if (!SAFE_REQUEST_PATHS.has(url.pathname) && !SESSION_REPLY_PATH.test(url.pathname)) {
    throw new Error(`unsupported plan-canvas request path: ${url.pathname}`);
  }
  return `${url.pathname}${url.search}`;
}

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Set a valid port: `--port 4319` or `ECC_PLAN_CANVAS_PORT=4319`.
  2. If server.json is corrupted, run `node scripts/plan-canvas.js stop` or delete the state directory to reset it.
  3. Validate env-provided ports upstream with an integer-range check before invoking the CLI.

Example fix

// before
ECC_PLAN_CANVAS_PORT=99999 node scripts/plan-canvas.js open plan.md
// after
ECC_PLAN_CANVAS_PORT=4319 node scripts/plan-canvas.js open plan.md
Defensive patterns

Strategy: validation

Validate before calling

function normalizePort(raw) {
  const n = Number(raw);
  if (!Number.isInteger(n) || n < 0 || n > 65535) {
    throw new Error(`Invalid port: ${raw}. Must be an integer in 0..65535.`);
  }
  return n;
}

Type guard

function isPort(value) {
  const n = Number(value);
  return Number.isInteger(n) && n >= 0 && n <= 65535;
}

Prevention

When it happens

Trigger: Setting ECC_PLAN_CANVAS_PORT to a non-numeric, float, or out-of-range value; passing `--port 99999` or `--port abc`; a corrupted server.json recording a malformed port. Number(port) accepts numeric strings but rejects mixed strings to NaN, which then fails Number.isInteger.

Common situations: Env var misconfiguration in CI; a stale/corrupted server.json after a crash; passing 0 is allowed (ephemeral bind) but negatives and >65535 are not.

Related errors


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