santifer/career-ops · error · Error

unexpected extra positional argument: ${arg}

Error message

unexpected extra positional argument: ${arg}

What it means

verify-cv-facts.mjs's parseCliArgs() takes at most one positional argument (the generated document to check); a second bare token throws this error. Guards against ambiguity about which file is target vs source — sources must use --source.

Source

Thrown at verify-cv-facts.mjs:442

  let targetArg = '';
  let configPath = DEFAULT_CONFIG;
  let json = false;
  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    if (arg === '--source' || arg === '--config') {
      if (!args[i + 1]) throw new Error(`${arg} requires a path`);
      if (arg === '--source') sourcePaths.push(args[++i]);
      else configPath = args[++i];
    } else if (arg === '--help' || arg === '-h') {
      return { help: true };
    } else if (arg === '--json') {
      json = true;
    } else if (arg.startsWith('--')) {
      throw new Error(`unknown option: ${arg}`);
    } else if (!targetArg) {
      targetArg = arg;
    } else {
      throw new Error(`unexpected extra positional argument: ${arg}`);
    }
  }
  return { targetArg, sourcePaths, configPath, json, help: false };
}

/** Return the command-line usage text. */
function usage() {
  return `Usage: node verify-cv-facts.mjs <generated-document> [--source path] [--config path] [--json]
       node verify-cv-facts.mjs --self-test

Checks generated candidate-facing text for unsupported metrics and explicitly asserted
non-metric facts (employers, titles, and tools) absent from source files.
Default sources: cv.md, article-digest.md
Default config:  config/cv-facts.json (optional)`;
}

/** Exercise the metric extraction regressions that the shared gate depends on. */
function runSelfTest() {

View on GitHub (pinned to 60398d6549)

Solutions

  1. Mark every source file explicitly: `node verify-cv-facts.mjs <target> --source <src1> --source <src2>`
  2. Delete the stray token if it was pasted by accident
  3. Quote/avoid globs that expand to more than the single target document

Example fix

# before
node verify-cv-facts.mjs output/cv.md cv.md
# after
node verify-cv-facts.mjs output/cv.md --source cv.md
Defensive patterns

Strategy: validation

Validate before calling

const positional = process.argv.slice(2).filter((a) => !a.startsWith('--') && !isFlagValue(a));
if (positional.length > 1) {
  console.error(`expected 1 target document, got ${positional.length}: ${positional.join(' ')}`);
  process.exit(2);
}

Try / catch

try {
  const { targetArg, sourcePaths } = parseCliArgs(args);
} catch (err) {
  if (/^unexpected extra positional argument:/.test(err.message)) {
    console.error(`${err.message}\nUse --source <path> for every source file.`);
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: `node verify-cv-facts.mjs doc1.md doc2.md`, or forgetting the --source flag so the source path lands positionally: `verify-cv-facts.mjs output/cv.md cv.md`.

Common situations: Muscle memory from tools that take multiple positional files; converting an old command where sources were positional; shell glob expansion matching two files.

Related errors


AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20). Data as JSON: /api/errors/83e4478c2c41e651. Report an issue: GitHub.