{"record":{"id":"bfeaa4f4263c9233","repo":"jackwener/OpenCLI","slug":"arxiv-label-must-be-a-positive-integer","errorCode":null,"errorMessage":"arxiv ${label} must be a positive integer","messagePattern":"arxiv (.+?) must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/arxiv/utils.js","lineNumber":21,"sourceCode":" *\n * arXiv exposes a public Atom/XML API — no key required.\n * https://info.arxiv.org/help/api/index.html\n */\nimport { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';\nexport const ARXIV_BASE = 'https://export.arxiv.org/api/query';\nconst ARXIV_CATEGORY_PATTERN = /^[a-z]+(?:-[a-z]+)*(?:\\.[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)?$/;\nexport async function arxivFetch(params) {\n    const resp = await fetch(`${ARXIV_BASE}?${params}`);\n    if (!resp.ok) {\n        throw new CommandExecutionError(`arXiv API HTTP ${resp.status}`, 'Check your search term or paper ID');\n    }\n    return resp.text();\n}\nexport function normalizeArxivLimit(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const limit = Number(raw);\n    if (!Number.isInteger(limit) || limit <= 0) {\n        throw new ArgumentError(`arxiv ${label} must be a positive integer`);\n    }\n    if (limit > maxValue) {\n        throw new ArgumentError(`arxiv ${label} must be <= ${maxValue}`);\n    }\n    return limit;\n}\nexport function normalizeArxivCategory(value) {\n    const category = String(value || '').trim();\n    if (!ARXIV_CATEGORY_PATTERN.test(category)) {\n        throw new ArgumentError(`Invalid arXiv category \"${value}\". Examples: cs.CL, cs.LG, math.PR, q-bio.NC, physics.comp-ph`);\n    }\n    return category;\n}\n/** Decode the small set of XML entities arXiv emits in text fields. */\nfunction decodeEntities(s) {\n    return s\n        .replace(/&amp;/g, '&')\n        .replace(/&lt;/g, '<')","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/arxiv/utils.js#L3-L39","documentation":"ArgumentError thrown by normalizeArxivLimit when the supplied limit (after ?? default) is not a positive integer (Number.isInteger fails or value <= 0). The library requires result limits to be whole numbers >= 1 so it can safely build the arXiv max_results parameter.","triggerScenarios":"Passing limit = 0, a negative number, a non-numeric string like 'ten', a float like 2.5, NaN, or null when no default is provided to normalizeArxivLimit.","commonSituations":"CLI users typing --limit 0 or --limit abc; config files with string limits that Number() coerces to NaN; off-by-one code passing 0 to disable limiting.","solutions":["Pass a positive integer (>= 1) for the limit option.","Validate/parse the user input to an integer before calling the command.","Omit the option to use the command's built-in default limit."],"exampleFix":"// before\nopencli arxiv search 'transformers' --limit 0\n// after\nopencli arxiv search 'transformers' --limit 10","handlingStrategy":"validation","validationCode":"function assertPositiveInt(v) {\n  const n = Number(v);\n  if (!Number.isInteger(n) || n <= 0) throw new Error(`limit must be a positive integer, got ${v}`);\n  return n;\n}\nconst limit = assertPositiveInt(opts.limit ?? 10);","typeGuard":"function isPositiveInt(v) {\n  return typeof v === 'number' && Number.isInteger(v) && v > 0;\n}","tryCatchPattern":"try {\n  await run(['arxiv', 'search', term, '--limit', String(limit)]);\n} catch (e) {\n  if (/must be a positive integer/.test(e.message)) {\n    console.error('Fix --limit: pass a whole number >= 1');\n  } else throw e;\n}","preventionTips":["Always coerce and validate CLI/config numbers with Number.isInteger before use.","Use schema validation (e.g. zod) on option objects.","Prefer omitting the option over passing 0 to 'disable' limiting."],"tags":["validation","arguments","input"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}