jackwener/OpenCLI · error · ArgumentError
juejin cursor must be a non-negative decimal integer
Error message
juejin cursor must be a non-negative decimal integer
What it means
requireCursor normalizes pagination cursors and throws an ArgumentError when a numeric cursor is not a non-negative safe integer. Negative numbers, floats, Infinity/NaN, and unsafe integers are all rejected, since Juejin article cursors are offsets/ids expressed as non-negative decimal integers.
Source
Thrown at clis/juejin/utils.js:59
n = Number(raw);
}
else {
throw new ArgumentError(`juejin ${label} must be a positive decimal integer`);
}
if (!Number.isSafeInteger(n) || n <= 0) {
throw new ArgumentError(`juejin ${label} must be a positive integer`);
}
if (n > maxValue) {
throw new ArgumentError(`juejin ${label} must be <= ${maxValue}`);
}
return n;
}
export function requireCursor(value) {
const raw = value ?? '0';
if (typeof raw === 'number') {
if (Number.isSafeInteger(raw) && raw >= 0) return String(raw);
throw new ArgumentError('juejin cursor must be a non-negative decimal integer');
}
if (typeof raw === 'string' && /^(0|[1-9]\d*)$/.test(raw)) {
return raw;
}
throw new ArgumentError('juejin cursor must be a non-negative decimal integer');
}
/** Resolve a `--category` arg to the underlying numeric category id. */
export function resolveCategory(value) {
if (value == null) return '';
const raw = String(value).trim();
if (!raw) return '';
if (JUEJIN_ID.test(raw)) return raw;
const slug = raw.toLowerCase();
if (CATEGORY_ALIASES[slug]) return CATEGORY_ALIASES[slug];
throw new ArgumentError(
`juejin category "${value}" is not recognised`,
`Use a category id (e.g. "${CATEGORY_ALIASES.backend}") or one of: ${Object.keys(CATEGORY_ALIASES).join(', ')}.`,View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a valid non-negative integer cursor (e.g. --cursor 0 to start over).
- Clamp/round before calling: n = Math.max(0, Math.floor(n)).
- Use the next_cursor value from the previous response verbatim instead of doing arithmetic on cursors.
- For very large ids, pass them as strings matching /^(0|[1-9]\d*)$/ to avoid float precision loss.
Example fix
// before
const next = Number(cursor) - pageSize; // can go negative
// after
const next = Math.max(0, Number(cursor) - pageSize);
cli({ cursor: String(next) }); Defensive patterns
Strategy: type-guard
Validate before calling
function validNumberCursor(n){ return typeof n === 'number' && Number.isSafeInteger(n) && n >= 0; }
// if (!validNumberCursor(cursor)) cursor = 0; Type guard
function isNonNegativeSafeInt(v){ return typeof v === 'number' && Number.isSafeInteger(v) && v >= 0; } Try / catch
try {
cli({ cursor });
} catch (e) {
if (/cursor must be a non-negative decimal integer/.test(e.message)) {
cli({ cursor: '0' }); // restart pagination
} else throw e;
} Prevention
- Never do arithmetic on cursors; always pass through the server-provided next_cursor.
- Clamp with Math.max(0, Math.floor(n)) when cursors are derived numerically.
- Keep large ids/cursors as strings to dodge float precision loss.
When it happens
Trigger: Passing --cursor -1, --cursor 1.5, --cursor 1e21, or a float to a command option that routes through requireCursor; programmatically passing a computed number that is negative or non-integer.
Common situations: Arithmetic on cursors producing negatives (cursor - pageSize when at the first page); JSON numbers parsed as floats; JavaScript precision loss converting a big cursor id to a float that is not a safe integer.
Related errors
- boss ${name} must be a positive integer
- ${flagLabel} must be a positive integer
- ${flagLabel} must be a non-negative integer
- coingecko limit must be <= 250 (per_page upper bound)
- coingecko page must be a positive integer
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/d8b9364689b9e8af.
Report an issue: GitHub.