{"record":{"id":"5ffc3ade2016f9eb","repo":"Hmbown/CodeWhale","slug":"attempts-must-be-an-integer-from-1-to-20","errorCode":null,"errorMessage":"--attempts must be an integer from 1 to 20","messagePattern":"--attempts must be an integer from 1 to 20","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/scripts/compare-deployed-facts.mjs","lineNumber":116,"sourceCode":"\nasync function main() {\n  const args = parseArgs(process.argv.slice(2));\n  let baseUrl;\n  try {\n    baseUrl = new URL(args.baseUrl);\n  } catch {\n    throw new Error(`invalid --base-url: ${args.baseUrl}`);\n  }\n  if (!/^https?:$/.test(baseUrl.protocol)) {\n    throw new Error(\"--base-url must use http or https\");\n  }\n\n  const expectedRevision = args.expectedRevision || localRevision();\n  if (!expectedRevision || !/^[0-9a-f]{40}$/i.test(expectedRevision)) {\n    throw new Error(\"expected revision must be an exact 40-character Git SHA\");\n  }\n  if (!Number.isInteger(args.attempts) || args.attempts < 1 || args.attempts > 20) {\n    throw new Error(\"--attempts must be an integer from 1 to 20\");\n  }\n  if (!Number.isFinite(args.retryDelayMs) || args.retryDelayMs < 0 || args.retryDelayMs > 30_000) {\n    throw new Error(\"--retry-delay-ms must be between 0 and 30000\");\n  }\n\n  const facts = buildFacts();\n  const expected = {\n    sourceRevision: expectedRevision,\n    version: facts.version,\n    providerCount: facts.providers.length,\n    toolCount: facts.toolCount,\n    latestPublishedRelease: facts.latestPublishedRelease,\n  };\n  const endpoint = new URL(\"/api/facts\", baseUrl).toString();\n  let last = { error: \"not attempted\" };\n  let differences = [];\n\n  for (let attempt = 1; attempt <= args.attempts; attempt += 1) {","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/web/scripts/compare-deployed-facts.mjs#L98-L134","documentation":"The --attempts option controls how many times the script polls the deployed facts. It must be an integer between 1 and 20 inclusive; anything else (non-integers, 0, negatives, values above 20) throws this error before any network work starts.","triggerScenarios":"Running with --attempts 0, --attempts 25, --attempts 2.5, or a non-numeric string like --attempts many.","commonSituations":"Trying to disable retries by passing 0, over-tuning poll counts past the cap, or quoting/parsing mistakes that turn the value into a non-integer.","solutions":["Pass an integer from 1 to 20, e.g. --attempts 5","If you need more polling, increase --retry-delay-ms or run the script again instead of raising attempts","Verify the shell passes the value as a plain integer without extra characters"],"exampleFix":"// before\nnode compare-deployed-facts.mjs --attempts 0\n// after\nnode compare-deployed-facts.mjs --attempts 3","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(attempts) || attempts < 1 || attempts > 20) throw new Error('attempts must be 1..20');","typeGuard":"const isValidAttempts = (v) => Number.isInteger(v) && v >= 1 && v <= 20;","tryCatchPattern":"try { run(args); } catch (e) { if (e.message.includes('--attempts')) { console.error('Use an integer 1-20'); process.exitCode = 2; } else throw e; }","preventionTips":["Clamp computed attempt counts to [1, 20]","Remember 0 does not disable retries — it is rejected","Parse CLI numbers with Number.parseInt and validate before use"],"tags":["cli","validation","arguments"],"backgroundTag":"value-out-of-range","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}