jackwener/OpenCLI · error · ArgumentError

semanticscholar ${label} must be a positive integer

Error message

semanticscholar ${label} must be a positive integer

What it means

requireBoundedInt coerces the `limit` argument (or another labeled int) to a number and throws ArgumentError when the value is not a positive integer — e.g. 0, negative numbers, NaN, or non-numeric strings. This ensures the API request always carries a valid page size.

Source

Thrown at clis/semanticscholar/utils.js:38

// arXiv ids: modern `YYMM.NNNNN` form or legacy `archive/YYMMNNN`.
const ARXIV_MODERN = /^\d{4}\.\d{4,5}(?:v\d+)?$/;
const ARXIV_LEGACY = /^[a-z-]+\/\d{7}(?:v\d+)?$/i;
// Other Semantic Scholar accepted prefixes that we pass through verbatim.
const PREFIXED = /^(ARXIV|MAG|ACL|PMID|PMCID|URL|CorpusId|DBLP):/i;

export function requireString(value, label) {
    const s = String(value ?? '').trim();
    if (!s) {
        throw new ArgumentError(`semanticscholar ${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(`semanticscholar ${label} must be a positive integer`);
    }
    if (n > maxValue) {
        throw new ArgumentError(`semanticscholar ${label} must be <= ${maxValue}`);
    }
    return n;
}

/**
 * Resolve a user-supplied paper reference to a Semantic Scholar paper id
 * segment. Accepts:
 *
 *   - bare Semantic Scholar paperId (40-char hex)
 *   - DOI (with or without `doi:` / `https://doi.org/` prefix)
 *   - arXiv id (`1706.03762` / `1706.03762v3` / `cs/0501067`)
 *   - typed prefixes Semantic Scholar accepts verbatim (`ARXIV:`, `MAG:`,
 *     `ACL:`, `PMID:`, `PMCID:`, `URL:`, `CorpusId:`, `DBLP:`)
 *   - full `https://www.semanticscholar.org/paper/<paperId>` URL
 */

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a whole number >= 1, e.g. `--limit 20`.
  2. Omit the flag entirely to use the default (20 for search).
  3. In scripts, validate before calling: `Number.isInteger(Number(raw)) && Number(raw) > 0`.

Example fix

// before
opencli semanticscholar search "transformers" --limit 0
// after
opencli semanticscholar search "transformers" --limit 20
Defensive patterns

Strategy: validation

Validate before calling

function parseLimit(raw, { def = 20, max = 100 } = {}) {
    if (raw == null || raw === '') return def;
    const n = Number(raw);
    if (!Number.isInteger(n) || n <= 0) throw new Error(`limit must be a positive integer, got ${raw}`);
    return n;
}

Type guard

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

Try / catch

try {
    await runSearch({ limit: args.limit });
} catch (err) {
    if (err instanceof ArgumentError && /positive integer/.test(err.message)) {
        console.error(`Bad --limit: ${err.message} (use e.g. --limit 20)`);
        process.exit(2);
    }
    throw err;
}

Prevention

When it happens

Trigger: Passing `--limit 0`, `--limit -5`, `--limit abc`, `--limit 2.5`, or `--limit ''` to a semanticscholar command; also a variable holding a non-numeric string passed as limit.

Common situations: Scripts computing limit from arithmetic that yields 0 or NaN; users assuming limit accepts 'all' or floats; locale-formatted numbers ('1,000') that Number() rejects.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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