{"record":{"id":"e61d1e10267f0eb3","repo":"jackwener/OpenCLI","slug":"juejin-label-must-be-a-positive-integer","errorCode":null,"errorMessage":"juejin ${label} must be a positive integer","messagePattern":"juejin (.+?) must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/juejin/utils.js","lineNumber":47,"sourceCode":"        throw new ArgumentError(`juejin ${label} cannot be empty`);\n    }\n    return s;\n}\n\nexport function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    let n;\n    if (typeof raw === 'number') {\n        n = raw;\n    }\n    else if (typeof raw === 'string' && /^[1-9]\\d*$/.test(raw)) {\n        n = Number(raw);\n    }\n    else {\n        throw new ArgumentError(`juejin ${label} must be a positive decimal integer`);\n    }\n    if (!Number.isSafeInteger(n) || n <= 0) {\n        throw new ArgumentError(`juejin ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`juejin ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\nexport function requireCursor(value) {\n    const raw = value ?? '0';\n    if (typeof raw === 'number') {\n        if (Number.isSafeInteger(raw) && raw >= 0) return String(raw);\n        throw new ArgumentError('juejin cursor must be a non-negative decimal integer');\n    }\n    if (typeof raw === 'string' && /^(0|[1-9]\\d*)$/.test(raw)) {\n        return raw;\n    }\n    throw new ArgumentError('juejin cursor must be a non-negative decimal integer');\n}","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/juejin/utils.js#L29-L65","documentation":"After the format check, requireBoundedInt re-checks semantic validity: the parsed number must be a safe integer and strictly greater than zero. This branch catches numbers and numeric strings that passed the regex path but are <= 0 or exceed Number.MAX_SAFE_INTEGER (e.g. very large digit strings), as well as defensive re-validation of numeric input like 0, -0, or NaN that reached the numeric branch.","triggerScenarios":"Passing --limit 0 or --limit -1 (when the numeric branch is taken), a string of digits longer than 2^53 (not a safe integer), or BigInt/NaN-ish values routed into the numeric path.","commonSituations":"Computing a limit via arithmetic that underflows to 0 (e.g. size * pages where size=0); passing Number.MAX_SAFE_INTEGER+1 from a generator; defaulting to 0 intending 'unlimited'.","solutions":["Use at least 1: --limit 1 for a minimal page.","Clamp computed values: n = Math.max(1, Math.min(maxValue, n)) before calling the CLI.","For large values, respect the command's documented max (the subsequent <= maxValue check gives the exact bound).","Omit the option to use the built-in default limit."],"exampleFix":"// before\nconst limit = rows.length; // 0 when empty -> throws\ncli({ limit });\n// after\nconst limit = Math.max(1, Math.min(50, rows.length || 20));\ncli({ limit });","handlingStrategy":"validation","validationCode":"function clampLimit(n, max){ n = Math.floor(Number(n)); if (!Number.isSafeInteger(n) || n <= 0) throw new Error('limit must be a positive safe integer'); return Math.min(n, max); }","typeGuard":"function isSafePositiveInt(v){ return typeof v === 'number' && Number.isSafeInteger(v) && v > 0; }","tryCatchPattern":"try {\n  cli({ limit });\n} catch (e) {\n  if (/must be a positive integer/.test(e.message)) {\n    cli({ limit: 20 });\n  } else throw e;\n}","preventionTips":["Guard computed limits: if (!Number.isSafeInteger(n) || n <= 0) use a default.","Avoid arithmetic that can yield 0 (empty arrays, zero sizes) feeding limit.","Remember digit strings beyond 2^53 are not safe integers — keep cursors/ids as strings but keep limits small."],"tags":["argument-validation","cli","input-validation","integer"],"backgroundTag":"invalid-numeric-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}