jackwener/OpenCLI · error · ArgumentError

wikidata ${label} must be a positive integer

Error message

wikidata ${label} must be a positive integer

What it means

requireBoundedInt validates numeric limit-style options for the wikidata adapter. It coerces the raw value to a number and throws an ArgumentError if the result is not a strictly positive integer. This keeps invalid limits (0, negative, fractional, non-numeric) from reaching the Wikidata API.

Source

Thrown at clis/wikidata/utils.js:27

export const WIKIDATA_BASE = 'https://www.wikidata.org';
const UA = 'opencli-wikidata-adapter/1.0 (+https://github.com/jackwener/opencli; mailto:opencli@example.com)';

// Q-ID = an item; P-ID = a property; L-ID = a lexeme. We accept all three so the
// adapter can be reused for properties / lexemes without a separate command, but
// search only returns Q-IDs by default.
const ENTITY_ID_PATTERN = /^[QPL]\d+$/;

export function requireString(value, label) {
    const s = String(value ?? '').trim();
    if (!s) throw new ArgumentError(`wikidata ${label} cannot be empty`);
    return s;
}

export function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {
    const raw = value ?? defaultValue;
    const n = typeof raw === 'number' ? raw : Number(raw);
    if (!Number.isInteger(n) || n <= 0) {
        throw new ArgumentError(`wikidata ${label} must be a positive integer`);
    }
    if (n > maxValue) {
        throw new ArgumentError(`wikidata ${label} must be <= ${maxValue}`);
    }
    return n;
}

export function requireEntityId(value) {
    const raw = String(value ?? '').trim().toUpperCase();
    if (!raw) throw new ArgumentError('wikidata entity id is required (e.g. "Q937")');
    // Tolerate URL-paste like `https://www.wikidata.org/wiki/Q937`.
    const stripped = raw.replace(/^HTTPS?:\/\/[^/]+\/WIKI\//i, '');
    if (!ENTITY_ID_PATTERN.test(stripped)) {
        throw new ArgumentError(
            `wikidata entity id "${value}" is not a valid Q/P/L identifier`,
            'Expected format: "Q<digits>" (item), "P<digits>" (property), or "L<digits>" (lexeme).',
        );
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a positive integer, e.g. --limit 10
  2. Check the value's source (env var, config) for stray characters or units
  3. If you want 'no cap', omit the limit option rather than passing 0
  4. Validate with Number.isInteger in your script before invoking

Example fix

// before
await runCli(['wikidata', 'search', 'cat', '--limit', '0']);
// after
await runCli(['wikidata', 'search', 'cat', '--limit', '10']);
Defensive patterns

Strategy: validation

Validate before calling

const n = Number(limit);
if (!Number.isInteger(n) || n <= 0) throw new Error(`limit must be a positive integer, got ${limit}`);
await runCli(['wikidata', 'search', query, '--limit', String(n)]);

Type guard

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

Try / catch

try {
    await runCli(['wikidata', 'search', query, '--limit', limit]);
} catch (e) {
    if (/must be a positive integer/.test(e.message)) {
        console.error(`Invalid --limit ${limit}; using default`);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling requireBoundedInt (via the `limit` option) with 0, a negative number, a float like 2.5, or a non-numeric string such as 'abc' or '10x'.

Common situations: Passing --limit 0 intending 'unlimited'; a CLI flag parsed from a string with stray characters; a config value of '20 items' instead of a bare number; off-by-one defaults of 0.

Related errors


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