jackwener/OpenCLI · error · ArgumentError

weread-official: ${label} must be a positive integer

Error message

weread-official: ${label} must be a positive integer

What it means

requirePositiveInt throws this when the supplied value is not made solely of digits (/^\d+$/ fails) — e.g. letters, negative numbers, floats, or units like '10px'. The validator intentionally lumps non-numeric text and integers < 1 into the same message to keep CLI feedback simple.

Source

Thrown at clis/weread-official/utils.js:268

export function requireBookId(value, label = 'bookId') {
    const text = requireText(value, label);
    if (!/^[A-Za-z0-9_-]+$/.test(text)) {
        throw new ArgumentError(`weread-official: ${label} contains invalid characters`, 'Pass a bookId from `weread-official search`.');
    }
    return text;
}

export function requirePositiveInt(value, label, { defaultValue, max } = {}) {
    if (value === undefined || value === null || value === '') {
        if (defaultValue === undefined) {
            throw new ArgumentError(`weread-official: ${label} is required`);
        }
        return defaultValue;
    }
    const text = String(value).trim();
    if (!/^\d+$/.test(text)) {
        throw new ArgumentError(`weread-official: ${label} must be a positive integer`);
    }
    const n = Number(text);
    if (!Number.isSafeInteger(n) || n < 1) {
        throw new ArgumentError(`weread-official: ${label} must be a positive integer`);
    }
    if (max !== undefined && n > max) {
        throw new ArgumentError(`weread-official: ${label} must be <= ${max}`);
    }
    return n;
}

export function requireChoice(value, choices, label, defaultValue) {
    const text = String(value ?? defaultValue ?? '').trim();
    if (!choices.includes(text)) {
        throw new ArgumentError(`weread-official: ${label} must be one of: ${choices.join(', ')}`);
    }
    return text;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Supply a plain positive integer literal, e.g. --count 10 (no signs, decimals, commas, or units).
  2. Sanitize the value in scripts: strip non-digits or coerce with parseInt and re-check before calling.
  3. If you need an 'unlimited' sentinel, use the documented max/default options instead of -1.
  4. Confirm you are passing the value to the right flag (a string flag instead of the count flag).

Example fix

// before
cli(['listNotebooks', '--count', '-1']);
// after
cli(['listNotebooks', '--count', '10']);
Defensive patterns

Strategy: validation

Validate before calling

const n = Number(String(value).trim());
if (!Number.isInteger(n) || n < 1) throw new Error(`count must be a positive integer, got: ${value}`);

Type guard

function isPositiveIntString(v) { return typeof v === 'number' ? Number.isSafeInteger(v) && v >= 1 : /^\d+$/.test(String(v).trim()) && Number(v) >= 1; }

Try / catch

try {
  await cli.run(['count', '--count', value]);
} catch (e) {
  if (e instanceof ArgumentError && /must be a positive integer/.test(e.message)) {
    console.error(`Bad --count value '${value}'; use an integer >= 1`); process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Passing --count abc, --count -3, --count 2.5, or a value with whitespace/units to count or listNotebooks; the regex test on the trimmed string fails.

Common situations: Typoed flags picking up string values ('ten'); scripts interpolating negative sentinel values (-1 meaning 'all'); locale-formatted numbers ('1,000'); stale scripts using old option semantics.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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