jackwener/OpenCLI · error · ArgumentError

juejin ${label} must be a positive decimal integer

Error message

juejin ${label} must be a positive decimal integer

What it means

requireBoundedInt validates numeric limit-like arguments. A value is accepted if it is a number or a string matching /^[1-9]\d*$/ (positive decimal integer without leading zeros). Anything else — floats, negatives, zero, hex/octal/underscored numbers, strings with signs or whitespace-only digits — triggers this ArgumentError before further range checks.

Source

Thrown at clis/juejin/utils.js:44

export function requireString(value, label) {
    const s = String(value ?? '').trim();
    if (!s) {
        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;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a plain positive integer: --limit 20.
  2. Sanitize the value before invoking: strip commas/whitespace, round floats with Math.floor.
  3. If the value comes from config/env, validate with /^[1-9]\d*$/.test(String(v).trim()) first.
  4. Use the default by omitting the option if a custom limit is not needed.

Example fix

// before
const n = parseFloat(input); // 2.5 -> throws downstream
cli({ limit: String(n) });
// after
const n = parseInt(input, 10);
if (!/^[1-9]\d*$/.test(String(n))) throw new Error('bad limit');
cli({ limit: String(n) });
Defensive patterns

Strategy: validation

Validate before calling

function toPositiveInt(v){ const s = String(v ?? '').trim().replace(/[,\s_]/g, ''); if (!/^[1-9]\d*$/.test(s)) throw new Error('limit must be a positive decimal integer'); return Number(s); }
// const limit = toPositiveInt(opts.limit);

Type guard

function isPositiveDecimalIntString(v){ return typeof v === 'string' && /^[1-9]\d*$/.test(v) || (typeof v === 'number' && Number.isInteger(v) && v > 0); }

Try / catch

try {
  cli({ limit });
} catch (e) {
  if (/must be a positive decimal integer/.test(e.message)) {
    cli({ limit: 20 }); // fall back to default page size
  } else throw e;
}

Prevention

When it happens

Trigger: Passing e.g. --limit 1.5, --limit -3, --limit 0x10, --limit "12 ", --limit +5, --limit 007, or a non-numeric string like --limit ten to any command whose limit option calls requireBoundedInt.

Common situations: Copy-pasting numbers with invisible whitespace or thousands separators (1,000); using a float from a config file; scripting with bc/awk output like '2.0'; locale-formatted numbers.

Related errors


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