jackwener/OpenCLI · error · ArgumentError

juejin ${label} must be a positive integer

Error message

juejin ${label} must be a positive integer

What it means

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.

Source

Thrown at clis/juejin/utils.js:47

        throw new ArgumentError(`juejin ${label} cannot be empty`);
    }
    return s;
}

export function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {
    const raw = value ?? defaultValue;
    let n;
    if (typeof raw === 'number') {
        n = raw;
    }
    else if (typeof raw === 'string' && /^[1-9]\d*$/.test(raw)) {
        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');
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use at least 1: --limit 1 for a minimal page.
  2. Clamp computed values: n = Math.max(1, Math.min(maxValue, n)) before calling the CLI.
  3. For large values, respect the command's documented max (the subsequent <= maxValue check gives the exact bound).
  4. Omit the option to use the built-in default limit.

Example fix

// before
const limit = rows.length; // 0 when empty -> throws
cli({ limit });
// after
const limit = Math.max(1, Math.min(50, rows.length || 20));
cli({ limit });
Defensive patterns

Strategy: validation

Validate before calling

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); }

Type guard

function isSafePositiveInt(v){ return typeof v === 'number' && Number.isSafeInteger(v) && v > 0; }

Try / catch

try {
  cli({ limit });
} catch (e) {
  if (/must be a positive integer/.test(e.message)) {
    cli({ limit: 20 });
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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'.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/e61d1e10267f0eb3. Report an issue: GitHub.