{"record":{"id":"c9fa93d3dcbf9a51","repo":"jackwener/OpenCLI","slug":"name-must-be-an-integer-between-1-and-max","errorCode":null,"errorMessage":"--${name} must be an integer between 1 and ${max}","messagePattern":"--(.+?) must be an integer between 1 and (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/openfda/utils.js","lineNumber":21,"sourceCode":"// Free public tier with anonymous rate limit (~240 req/min, 1000 req/day per IP).\n// API key bumps that to 240 req/min × ~120000 req/day, but is not required for\n// modest read traffic.\nimport { ArgumentError, EmptyResultError, CommandExecutionError } from '@jackwener/opencli/errors';\n\nexport const OPENFDA_BASE = 'https://api.fda.gov';\nconst UA = 'opencli-openfda/1.0';\n\nexport function requireString(value, name) {\n    if (typeof value !== 'string' || !value.trim()) {\n        throw new ArgumentError(`--${name} is required`);\n    }\n    return value.trim();\n}\n\nexport function requireBoundedInt(value, def, max, name = 'limit') {\n    const n = value == null || value === '' ? def : Number(value);\n    if (!Number.isInteger(n) || n < 1 || n > max) {\n        throw new ArgumentError(`--${name} must be an integer between 1 and ${max}`);\n    }\n    return n;\n}\n\nexport async function openfdaFetch(url, label) {\n    let resp;\n    try {\n        resp = await fetch(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });\n    } catch (err) {\n        throw new CommandExecutionError(`${label} request failed: ${err.message}`);\n    }\n    if (resp.status === 404) {\n        // openFDA returns 404 for \"no matches\" instead of an empty results array.\n        throw new EmptyResultError(label, `${label} returned 404 (no matches).`);\n    }\n    if (resp.status === 429) {\n        throw new CommandExecutionError(`${label} rate-limited (HTTP 429); back off and retry.`);\n    }","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/openfda/utils.js#L3-L39","documentation":"requireBoundedInt coerces an option to a number and enforces that it is an integer within [1, max] (defaults applied when empty), throwing ArgumentError otherwise. It protects the openFDA API from invalid limit values that would be rejected server-side. The message names the flag and the allowed range.","triggerScenarios":"Passing --limit 0, a negative number, a non-integer like 2.5, a non-numeric string like 'ten', or a value above the endpoint max (e.g. --limit 5000). Empty/null falls back to the default and does not throw.","commonSituations":"User assumes the limit is unbounded and asks for thousands of rows; a script passes a float computed from arithmetic; a typo like '--limit 1oo' is coerced to NaN; confusing 1-based vs 0-based bounds.","solutions":["Set --limit to an integer between 1 and the endpoint's max (openFDA caps at 1000; the CLI enforces its own max).","Omit the flag entirely to use the built-in default.","In scripts, validate/round the number before passing: limit=Math.min(1000, Math.max(1, Math.trunc(n))).","Check the CLI's --help for the accepted range."],"exampleFix":"// before\nopencli openfda food-recall --limit 0        # throws\n// after\nopencli openfda food-recall --limit 25","handlingStrategy":"validation","validationCode":"function ensureBoundedLimit(value, max = 1000, def = 10) {\n  const n = value == null || value === '' ? def : Number(value);\n  if (!Number.isInteger(n) || n < 1 || n > max) {\n    throw new Error(`--limit must be an integer between 1 and ${max}`);\n  }\n  return n;\n}","typeGuard":"function isBoundedInt(v, max) {\n  const n = Number(v);\n  return Number.isInteger(n) && n >= 1 && n <= max;\n}","tryCatchPattern":"try {\n  const rows = await fetchFoodRecalls({ limit });\n} catch (e) {\n  if (e instanceof ArgumentError && /must be an integer/.test(e.message)) {\n    console.error(`${e.message} — try --limit 25`);\n    process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Clamp user input: Math.min(max, Math.max(1, Math.trunc(n))).","Never build limits from float arithmetic; use Math.trunc.","Document the accepted range in --help.","Reject non-numeric strings before calling the API wrapper."],"tags":["argument-validation","cli","bounds-check","openfda"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}