{"record":{"id":"6f60a9a6ccd0c947","repo":"santifer/career-ops","slug":"months-must-be-an-integer-from-1-to-120","errorCode":null,"errorMessage":"--months must be an integer from 1 to 120","messagePattern":"--months must be an integer from 1 to 120","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"company-funded.mjs","lineNumber":130,"sourceCode":"    help: false,\n  };\n  for (let i = 0; i < argv.length; i++) {\n    const arg = argv[i];\n    if (arg === '--dry-run') opts.dryRun = true;\n    else if (arg === '--json') opts.json = true;\n    else if (arg === '--self-test') opts.selfTest = true;\n    else if (arg === '--help' || arg === '-h') opts.help = true;\n    else if (arg === '--limit') opts.limit = Number(argv[++i] || '');\n    else if (arg === '--months') opts.months = Number(argv[++i] || '');\n    else if (arg === '--sort') opts.sort = String(argv[++i] || '').trim().toLowerCase();\n    else if (arg === '--sources') opts.sources = parseSources(argv[++i] || '');\n    else throw new Error(`unknown option: ${arg}`);\n  }\n  if (!Number.isInteger(opts.limit) || opts.limit <= 0 || opts.limit > 100) {\n    throw new Error('--limit must be an integer from 1 to 100');\n  }\n  if (!Number.isInteger(opts.months) || opts.months <= 0 || opts.months > 120) {\n    throw new Error('--months must be an integer from 1 to 120');\n  }\n  if (!['date', 'score'].includes(opts.sort)) {\n    throw new Error('--sort must be date or score');\n  }\n  return opts;\n}\n\nfunction parseSources(value) {\n  const out = String(value || '')\n    .split(',')\n    .map((s) => normalizeSourceName(s.trim()))\n    .filter(Boolean);\n  const unique = [...new Set(out)];\n  const allowed = new Set(['techcrunch', 'prnewswire', 'guardian', 'hn']);\n  for (const source of unique) {\n    if (!allowed.has(source)) throw new Error(`unknown source in --sources: ${source}`);\n  }\n  return unique.length ? unique : [...DEFAULT_SOURCES];","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/company-funded.mjs#L112-L148","documentation":"CLI argument validation in company-funded.mjs's parseArgs: the --months value (coerced with Number()) failed the integer range check — it is NaN (missing or non-numeric argument), a non-integer, or outside 1-120. The input at fault is the token immediately after --months on the command line.","triggerScenarios":"`--months 0`, `--months 200`, `--months \"6 months\"` (NaN), `--months 1.5`, or `--months` with no following value (Number('') → NaN).","commonSituations":"Requesting a lookback window longer than the supported 10 years; passing a human-readable duration string; unit confusion (passing days or weeks where months are expected); CI variables with empty values.","solutions":["Pass an integer from 1 to 120, e.g. `--months 12`.","Convert other duration units to months before invoking (days/30, weeks/4.33 — floored).","Clamp in wrapper scripts: Math.min(120, Math.max(1, value)).","Ensure the value follows the flag as a separate argv token."],"exampleFix":"// before\nnode company-funded.mjs --months 365\n\n// after\nnode company-funded.mjs --months 12","handlingStrategy":"validation","validationCode":"function validMonths(n) {\n  const v = Number(n);\n  return Number.isInteger(v) && v > 0 && v <= 120 ? v : null;\n}\n// if (validMonths(cfg.lookbackMonths) === null) throw new Error('lookbackMonths must be 1-120');","typeGuard":"const isMonthsInRange = (v) => Number.isInteger(v) && v >= 1 && v <= 120;","tryCatchPattern":"try {\n  run(['--months', String(months)]);\n} catch (e) {\n  if (e.message.includes('--months must be')) {\n    console.warn('Clamping months to 120 and retrying');\n    run(['--months', '120']);\n  } else throw e;\n}","preventionTips":["Convert days/weeks to integer months (floored, capped at 120) before invoking.","Never pass human-readable duration strings to numeric flags.","Clamp in shared run wrappers.","Watch for unit confusion between similar flags (--limit vs --months)."],"tags":["cli","validation","argument-parsing"],"backgroundTag":"value-out-of-range","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}