{"record":{"id":"9cc72c9b16ed2aac","repo":"jackwener/OpenCLI","slug":"label-must-be-a-positive-integer-9cc72c","errorCode":null,"errorMessage":"${label} must be a positive integer","messagePattern":"(.+?) must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/hltv/utils.js","lineNumber":66,"sourceCode":"  overpass: 'de_overpass',\n  cache: 'de_cache',\n  cobblestone: 'de_cobblestone',\n  season: 'de_season',\n  train: 'de_train',\n  tuscan: 'de_tuscan',\n  vertigo: 'de_vertigo',\n};\n\nexport const VERSIONS = {\n  both: null,\n  cs2: 'CS2',\n  csgo: 'CSGO',\n};\n\nexport function normalizeLimit(value, defaultValue, maxValue, label = 'limit') {\n  const raw = value ?? defaultValue;\n  const n = Number(raw);\n  if (!Number.isInteger(n) || n <= 0) throw new ArgumentError(`${label} must be a positive integer`);\n  if (n > maxValue) throw new ArgumentError(`${label} must be <= ${maxValue}`);\n  return n;\n}\n\nexport function normalizeOffset(value, defaultValue = 0) {\n  const raw = value ?? defaultValue;\n  const n = Number(raw);\n  if (!Number.isInteger(n) || n < 0) throw new ArgumentError('offset must be a non-negative integer');\n  if (n % 100 !== 0) throw new ArgumentError('offset must be a multiple of 100');\n  return n;\n}\n\nexport function normalizeChoice(value, defaultValue, choices, label) {\n  const raw = String(value ?? defaultValue);\n  if (!Object.prototype.hasOwnProperty.call(choices, raw)) {\n    throw new ArgumentError(`${label} must be one of: ${Object.keys(choices).join(', ')}`);\n  }\n  return raw;","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/hltv/utils.js#L48-L84","documentation":"normalizeLimit validates a numeric limit option: it must be an integer greater than 0, else this ArgumentError is thrown. It defaults the value when null/undefined and is called by the limit helpers and commands with a limit option.","triggerScenarios":"Passing limit=0, a negative number, a non-integer like 2.5, a non-numeric string like 'ten', or NaN/Infinity to any command or helper accepting a limit option.","commonSituations":"CLI flag parsed from a string that was never converted to a number; computing a limit from a division producing a float; user enters 0 or negative 'to get everything'; JSON config containing a string limit.","solutions":["Pass a positive integer (>=1), e.g. limit: 10","Coerce CLI/config strings with Number() and validate before calling","Use Math.trunc/Math.floor on computed values to guarantee integers","Catch ArgumentError and fall back to the default limit"],"exampleFix":"// before\nawait run('search', { query: 'niko', limit: rawFlag }); // rawFlag is '20' (string)\n// after\nconst n = Number(rawFlag);\nawait run('search', { query: 'niko', limit: Number.isInteger(n) && n > 0 ? n : 10 });","handlingStrategy":"validation","validationCode":"function safeLimit(v, dflt = 10, max = 50) {\n  const n = Number(v);\n  return Number.isInteger(n) && n > 0 && n <= max ? n : dflt;\n}\n// args.limit = safeLimit(rawLimit);","typeGuard":"function isPositiveInt(v) { return typeof v === 'number' && Number.isInteger(v) && v > 0; }","tryCatchPattern":"try {\n  await command(page, { ...args, limit });\n} catch (err) {\n  if (err instanceof ArgumentError && /must be a positive integer/.test(err.message)) {\n    return command(page, { ...args, limit: 10 }); // fall back to default\n  }\n  throw err;\n}","preventionTips":["Coerce CLI/config values with Number() before passing limits","Guard computed limits for float/NaN results with Math.trunc","Never allow 0 or negatives as 'unlimited' — use the max value instead","Centralize limit parsing in one helper so all commands get the same guard"],"tags":["argument-error","validation","limit"],"backgroundTag":"invalid-numeric-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}