{"record":{"id":"284adaab486a5b79","repo":"jackwener/OpenCLI","slug":"archive-snapshots-limit-must-be-a-positive-integer","errorCode":null,"errorMessage":"archive snapshots limit must be a positive integer","messagePattern":"archive snapshots limit must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/archive/snapshots.js","lineNumber":47,"sourceCode":"    browser: false,\n    args: [\n        { name: 'url', positional: true, required: true, help: 'URL to look up (with or without scheme).' },\n        { name: 'from', type: 'string', required: false, help: 'Earliest year/timestamp (YYYY[MM[DD[hh[mm[ss]]]]])' },\n        { name: 'to', type: 'string', required: false, help: 'Latest year/timestamp (YYYY[MM[DD[hh[mm[ss]]]]])' },\n        { name: 'limit', type: 'int', default: 20, help: 'Max snapshots to return (max 1000).' },\n    ],\n    columns: ['timestamp', 'snapshot_url', 'status', 'mimetype', 'original_url'],\n    func: async (args) => {\n        const target = String(args.url ?? '').trim();\n        if (!target) {\n            throw new ArgumentError(\n                'archive snapshots url cannot be empty',\n                'Example: opencli archive snapshots wikipedia.org',\n            );\n        }\n        const limit = Number(args.limit ?? 20);\n        if (!Number.isInteger(limit) || limit <= 0) {\n            throw new ArgumentError('archive snapshots limit must be a positive integer');\n        }\n        if (limit > 1000) {\n            throw new ArgumentError('archive snapshots limit must be <= 1000');\n        }\n        for (const key of ['from', 'to']) {\n            const v = args[key];\n            if (v != null && !/^\\d{4,14}$/.test(String(v))) {\n                throw new ArgumentError(`archive snapshots ${key} must be a digit-only timestamp (YYYY[MM[DD[hh[mm[ss]]]]])`);\n            }\n        }\n\n        // Wayback CDX is served on HTTP only; the HTTPS endpoint returns 503.\n        const apiUrl = new URL('http://web.archive.org/cdx/search/cdx');\n        apiUrl.searchParams.set('url', target);\n        apiUrl.searchParams.set('output', 'json');\n        apiUrl.searchParams.set('limit', String(limit));\n        if (args.from) apiUrl.searchParams.set('from', String(args.from));\n        if (args.to) apiUrl.searchParams.set('to', String(args.to));","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/archive/snapshots.js#L29-L65","documentation":"ArgumentError thrown when the `limit` argument for `opencli archive snapshots` is not an integer greater than 0. The default is 20, so this fires only when the user explicitly passes a bad limit such as 0, a negative number, or a non-integer. It is client-side validation before any network call.","triggerScenarios":"Running `opencli archive snapshots <url> --limit 0`, a negative value, or a non-integer (e.g. --limit 1.5 or --limit abc that coerces to NaN).","commonSituations":"Shell variables expanding to empty or garbage; copy-pasting a limit with units ('50 results'); confusing limit 0 with 'unlimited'.","solutions":["Pass a positive integer: opencli archive snapshots wikipedia.org --limit 50","Omit --limit entirely to use the default of 20.","In scripts, sanitize the value: LIMIT=$(( ${LIMIT:-20} > 0 ? ${LIMIT:-20} : 20 ))."],"exampleFix":"// before\nopencli archive snapshots example.org --limit 0\n// after\nopencli archive snapshots example.org --limit 20","handlingStrategy":"validation","validationCode":"// shell\nLIMIT=${LIMIT:-20}\ncase \"$LIMIT\" in ''|*[!0-9]*) echo \"limit must be a positive integer\" >&2; exit 1;; esac\n[ \"$LIMIT\" -gt 0 ] || { echo \"limit must be positive\" >&2; exit 1; }\nopencli archive snapshots \"$URL\" --limit \"$LIMIT\"\n// node\nconst n = Number(raw);\nif (!Number.isInteger(n) || n <= 0) throw new Error('limit must be a positive integer');","typeGuard":"function isPositiveInt(v) {\n  return Number.isInteger(v) && v > 0;\n}","tryCatchPattern":"try {\n  await run(['archive', 'snapshots', url, '--limit', String(limit)]);\n} catch (e) {\n  if (/limit must be a positive integer/.test(e.message)) {\n    limit = 20; // fall back to default and retry\n  } else throw e;\n}","preventionTips":["Sanitize numeric CLI inputs from env/variables before passing them.","Use the default (20) when unsure instead of guessing 0.","Strip units or formatting from numbers extracted from text."],"tags":["argument-validation","cli-input","user-input","archive-org"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}