{"record":{"id":"a66e770c4c07b2d4","repo":"jackwener/OpenCLI","slug":"semanticscholar-label-must-be-maxvalue","errorCode":null,"errorMessage":"semanticscholar ${label} must be <= ${maxValue}","messagePattern":"semanticscholar (.+?) must be <= (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/semanticscholar/utils.js","lineNumber":41,"sourceCode":"// Other Semantic Scholar accepted prefixes that we pass through verbatim.\nconst PREFIXED = /^(ARXIV|MAG|ACL|PMID|PMCID|URL|CorpusId|DBLP):/i;\n\nexport function requireString(value, label) {\n    const s = String(value ?? '').trim();\n    if (!s) {\n        throw new ArgumentError(`semanticscholar ${label} cannot be empty`);\n    }\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(`semanticscholar ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`semanticscholar ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\n/**\n * Resolve a user-supplied paper reference to a Semantic Scholar paper id\n * segment. Accepts:\n *\n *   - bare Semantic Scholar paperId (40-char hex)\n *   - DOI (with or without `doi:` / `https://doi.org/` prefix)\n *   - arXiv id (`1706.03762` / `1706.03762v3` / `cs/0501067`)\n *   - typed prefixes Semantic Scholar accepts verbatim (`ARXIV:`, `MAG:`,\n *     `ACL:`, `PMID:`, `PMCID:`, `URL:`, `CorpusId:`, `DBLP:`)\n *   - full `https://www.semanticscholar.org/paper/<paperId>` URL\n */\nexport function requirePaperRef(value) {\n    const raw = String(value ?? '').trim();\n    if (!raw) {","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/semanticscholar/utils.js#L23-L59","documentation":"requireBoundedInt enforces an upper bound on integer arguments (label defaults to 'limit'): when the value exceeds maxValue (e.g. 100 for search), it throws ArgumentError naming the cap. The bound mirrors what the Semantic Scholar API accepts per page so requests are never rejected upstream.","triggerScenarios":"Passing `--limit 101` or higher to search (max 100), or exceeding any other labeled maxValue; scripts generating page sizes above the cap.","commonSituations":"Users trying to 'fetch everything' with a huge limit instead of paginating; hardcoded constants copied from APIs with higher caps; loops adding offset without respecting per-request limits.","solutions":["Lower the value to the cap (e.g. `--limit 100` for search).","Paginate: issue multiple requests with offset to retrieve more results.","Clamp programmatically: `const lim = Math.min(requested, 100);`"],"exampleFix":"// before\nconst limit = requireBoundedInt(args.limit, 20, 100); // throws for 500\n// after\nconst limit = requireBoundedInt(Math.min(Number(args.limit) || 20, 100), 20, 100);","handlingStrategy":"validation","validationCode":"const MAX = 100;\nconst requested = Number(args.limit ?? 20);\nif (requested > MAX) throw new Error(`--limit must be <= ${MAX}; paginate with offset instead`);","typeGuard":"function isWithinBound(n, max) { return Number.isInteger(n) && n > 0 && n <= max; }","tryCatchPattern":"try {\n    await runSearch({ limit });\n} catch (err) {\n    if (err instanceof ArgumentError && /must be <=/.test(err.message)) {\n        console.error(`${err.message}; use multiple requests with offset to page through results.`);\n        process.exit(2);\n    }\n    throw err;\n}","preventionTips":["Clamp user input: Math.min(Number(x) || default, maxValue).","Implement pagination (offset + limit<=100) instead of raising the limit.","Centralize bounds in constants so call sites cannot drift from the API cap.","Document the cap in scripts' help/usage text."],"tags":["argument-validation","cli","pagination"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}