{"record":{"id":"cdf8ec7a6d35bc62","repo":"jackwener/OpenCLI","slug":"rest-countries-label-must-be-a-positive-integer","errorCode":null,"errorMessage":"rest-countries ${label} must be a positive integer","messagePattern":"rest-countries (.+?) must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/rest-countries/utils.js","lineNumber":32,"sourceCode":"// Fields the adapter always requests; keep this list aligned with `columns` so\n// rows never have null-where-absent silent drops.\nexport const COUNTRY_FIELDS = [\n    'name', 'cca2', 'cca3', 'ccn3', 'capital', 'region', 'subregion',\n    'population', 'area', 'languages', 'currencies', 'flag', 'latlng', 'timezones',\n    'independent', 'unMember', 'landlocked',\n].join(',');\n\nexport function requireString(value, label) {\n    const s = String(value ?? '').trim();\n    if (!s) throw new ArgumentError(`rest-countries ${label} cannot be empty`);\n    return s;\n}\n\nexport function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const n = typeof raw === 'number' ? raw : Number(raw);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`rest-countries ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`rest-countries ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\nexport function requireRegion(value) {\n    const raw = String(value ?? '').trim().toLowerCase();\n    if (!raw) throw new ArgumentError('rest-countries region is required (e.g. \"europe\", \"asia\")');\n    if (!REST_COUNTRIES_REGIONS.has(raw)) {\n        throw new ArgumentError(\n            `rest-countries region \"${value}\" is not recognised`,\n            `Allowed regions: ${[...REST_COUNTRIES_REGIONS].join(', ')}.`,\n        );\n    }\n    return raw;\n}","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/rest-countries/utils.js#L14-L50","documentation":"requireBoundedInt coerces its input to a number and throws ArgumentError if the result is not a positive integer. This catches NaN, floats, zero, negatives, and non-numeric strings. It exists so the limit argument is always a sane count before building API requests.","triggerScenarios":"Passing limit values like 0, -5, 'abc', 2.5, or '' to a rest-countries command so `Number.isInteger(n) || n <= 0` fails at clis/rest-countries/utils.js:32.","commonSituations":"User typing a non-numeric CLI flag value; a config file containing '25 countries'; floating-point math producing a fractional limit; empty string from an unset env var.","solutions":["Pass limit as a positive whole number (>= 1).","Coerce and validate the value (Number.isInteger) before calling the command.","Omit limit to use the command's default.","Catch ArgumentError and re-prompt or fall back to the default."],"exampleFix":"// before\nawait countryCommand({ name: 'france', limit: 'ten' });\n// after\nawait countryCommand({ name: 'france', limit: 10 });","handlingStrategy":"validation","validationCode":"const n = Number(rawLimit);\nif (!Number.isInteger(n) || n <= 0) {\n  throw new TypeError('limit must be a positive integer');\n}","typeGuard":"function isPositiveInt(v) {\n  const n = typeof v === 'number' ? v : Number(v);\n  return Number.isInteger(n) && n > 0;\n}","tryCatchPattern":"try {\n  await countryCommand({ name, limit: rawLimit });\n} catch (err) {\n  if (err instanceof ArgumentError && /positive integer/.test(err.message)) {\n    return countryCommand({ name }); // fall back to default limit\n  }\n  throw err;\n}","preventionTips":["Parse CLI numeric flags with an explicit coercion + Number.isInteger check.","Reject empty strings early — Number('') is 0 and will fail.","Prefer omitting limit to using the default rather than guessing values.","Cover argument coercion with unit tests."],"tags":["argument-error","validation","type-error","cli"],"backgroundTag":"invalid-argument-type","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}