{"record":{"id":"487e9822644b7442","repo":"tinyhumansai/openhuman","slug":"unknown-arg-a","errorCode":null,"errorMessage":"unknown arg: ${a}","messagePattern":"unknown arg: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/rabbit/cli.mjs","lineNumber":71,"sourceCode":"\nfunction parseArgs(argv) {\n  const out = {\n    cmd: argv[0] ?? \"run\",\n    max: 5,\n    dryRun: false,\n    pr: null,\n    graceSec: 30,\n  };\n  for (let i = 1; i < argv.length; i++) {\n    const a = argv[i];\n    if (a === \"--dry-run\") out.dryRun = true;\n    else if (a === \"--max\") out.max = Number(argv[++i]);\n    else if (a === \"--pr\") out.pr = Number(argv[++i]);\n    else if (a === \"--grace\") out.graceSec = Number(argv[++i]);\n    else if (a === \"-h\" || a === \"--help\") {\n      out.cmd = \"help\";\n    } else {\n      throw new Error(`unknown arg: ${a}`);\n    }\n  }\n  return out;\n}\n\n// Convert \"1 hour and 5 minutes and 30 seconds\" / \"46 seconds\" / \"5 minutes\"\n// to seconds. CR uses `**46 seconds**` style — strip markdown asterisks first.\nfunction parseWaitSeconds(body) {\n  const m = body.match(/Please wait\\s+([^.<]+?)\\s+before requesting/i);\n  if (!m) return null;\n  const raw = m[1].replace(/\\*+/g, \"\").trim();\n  const parts = raw.split(/\\s*(?:,|and)\\s*/i);\n  let total = 0;\n  for (const part of parts) {\n    const pm = part.match(/^(\\d+)\\s*(second|minute|hour)s?$/i);\n    if (!pm) return null;\n    const n = Number(pm[1]);\n    const unit = pm[2].toLowerCase();","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/rabbit/cli.mjs#L53-L89","documentation":"Strict argument parsing in scripts/rabbit/cli.mjs: after the subcommand (default `run`), only --dry-run, --max <n>, --pr <n>, --grace <sec> and -h/--help are recognized. Any other token throws `unknown arg` immediately.","triggerScenarios":"Passing `--limit 10` (should be `--max 10`), `--force`, or abbreviations the parser does not support; also a flag whose expected value is missing silently consumes the next token, which can surface as a confusing unknown-arg one position later.","commonSituations":"Guessing flag names by analogy with gh/other repo CLIs; copy-pasting a command from an older revision of the script.","solutions":["Run `node scripts/rabbit/cli.mjs -h` (or `help`) to list accepted args","Map guesses to real flags: use `--max` for a count, `--pr` to target one PR, `--grace` for the wait override","Remove unsupported flags — there is no --force/--yes in this CLI; safety is expressed via --dry-run"],"exampleFix":"# before\nnode scripts/rabbit/cli.mjs run --limit 3 --force\n\n# after\nnode scripts/rabbit/cli.mjs run --max 3 --dry-run","handlingStrategy":"validation","validationCode":"const KNOWN = new Set(['--dry-run', '--max', '--pr', '--grace', '-h', '--help']);\nconst unknown = argv.filter(a => a.startsWith('--') && !KNOWN.has(a));\nif (unknown.length) {\n  console.error(`Unknown args: ${unknown.join(', ')} — allowed: --dry-run --max N --pr N --grace N -h/--help`);\n  process.exit(2);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run the subcommand with -h before scripting it in CI; the parser is strict and rejects invented flags","Copy the flag list verbatim from help output into pipeline definitions"],"tags":["cli","validation"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}