{"record":{"id":"83e4478c2c41e651","repo":"santifer/career-ops","slug":"unexpected-extra-positional-argument-arg","errorCode":null,"errorMessage":"unexpected extra positional argument: ${arg}","messagePattern":"unexpected extra positional argument: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"verify-cv-facts.mjs","lineNumber":442,"sourceCode":"  let targetArg = '';\n  let configPath = DEFAULT_CONFIG;\n  let json = false;\n  for (let i = 0; i < args.length; i++) {\n    const arg = args[i];\n    if (arg === '--source' || arg === '--config') {\n      if (!args[i + 1]) throw new Error(`${arg} requires a path`);\n      if (arg === '--source') sourcePaths.push(args[++i]);\n      else configPath = args[++i];\n    } else if (arg === '--help' || arg === '-h') {\n      return { help: true };\n    } else if (arg === '--json') {\n      json = true;\n    } else if (arg.startsWith('--')) {\n      throw new Error(`unknown option: ${arg}`);\n    } else if (!targetArg) {\n      targetArg = arg;\n    } else {\n      throw new Error(`unexpected extra positional argument: ${arg}`);\n    }\n  }\n  return { targetArg, sourcePaths, configPath, json, help: false };\n}\n\n/** Return the command-line usage text. */\nfunction usage() {\n  return `Usage: node verify-cv-facts.mjs <generated-document> [--source path] [--config path] [--json]\n       node verify-cv-facts.mjs --self-test\n\nChecks generated candidate-facing text for unsupported metrics and explicitly asserted\nnon-metric facts (employers, titles, and tools) absent from source files.\nDefault sources: cv.md, article-digest.md\nDefault config:  config/cv-facts.json (optional)`;\n}\n\n/** Exercise the metric extraction regressions that the shared gate depends on. */\nfunction runSelfTest() {","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/santifer/career-ops/blob/60398d6549a46f5266929538af21cfab94badc75/verify-cv-facts.mjs#L424-L460","documentation":"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.","triggerScenarios":"`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`.","commonSituations":"Muscle memory from tools that take multiple positional files; converting an old command where sources were positional; shell glob expansion matching two files.","solutions":["Mark every source file explicitly: `node verify-cv-facts.mjs <target> --source <src1> --source <src2>`","Delete the stray token if it was pasted by accident","Quote/avoid globs that expand to more than the single target document"],"exampleFix":"# before\nnode verify-cv-facts.mjs output/cv.md cv.md\n# after\nnode verify-cv-facts.mjs output/cv.md --source cv.md","handlingStrategy":"validation","validationCode":"const positional = process.argv.slice(2).filter((a) => !a.startsWith('--') && !isFlagValue(a));\nif (positional.length > 1) {\n  console.error(`expected 1 target document, got ${positional.length}: ${positional.join(' ')}`);\n  process.exit(2);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const { targetArg, sourcePaths } = parseCliArgs(args);\n} catch (err) {\n  if (/^unexpected extra positional argument:/.test(err.message)) {\n    console.error(`${err.message}\\nUse --source <path> for every source file.`);\n    process.exit(2);\n  }\n  throw err;\n}","preventionTips":["One positional target only; all sources go through repeated --source flags","Quote globs you do not want expanded","Copy the canonical invocation from usage(), not from a sibling tool"],"tags":["cli","argument-parsing","usage-error"],"backgroundTag":"unexpected-cli-argument","analyzedSha":"60398d6549a46f5266929538af21cfab94badc75","analyzedAt":"2026-08-20T23:00:06.764Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}