jackwener/OpenCLI · error · ArgumentError

${label} must be a positive integer

Error message

${label} must be a positive integer

What it means

ArgumentError from normalizeLimit in clis/stackoverflow/utils.js when a --limit value is not a positive integer. By design the helper never silently clamps: Number.isInteger(limit) must be true and limit must be > 0. Note Number('') === 0 and Number('3.5') is fractional, both of which fail.

Source

Thrown at clis/stackoverflow/utils.js:23

// We always set `site=stackoverflow` and decode the gzipped/HTML body via the
// returned JSON envelope.
import {
    ArgumentError,
    CommandExecutionError,
    EmptyResultError,
} from '@jackwener/opencli/errors';

export const SE_API = 'https://api.stackexchange.com/2.3';
export const SE_SITE = 'stackoverflow';

const UA = 'opencli-stackoverflow (+https://github.com/jackwener/opencli)';

/** Validate `limit` per typed-fail-fast convention (no silent clamp). */
export function normalizeLimit(value, defaultValue, maxValue, label = 'limit') {
    const raw = value ?? defaultValue;
    const limit = Number(raw);
    if (!Number.isInteger(limit) || limit <= 0) {
        throw new ArgumentError(`${label} must be a positive integer`);
    }
    if (limit > maxValue) {
        throw new ArgumentError(`${label} must be <= ${maxValue}`);
    }
    return limit;
}

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

/** Fetch a Stack Exchange API endpoint and return parsed JSON envelope. */
export async function seFetch(path, { searchParams } = {}) {
    const url = new URL(path.startsWith('http') ? path : `${SE_API}${path.startsWith('/') ? '' : '/'}${path}`);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a positive integer, e.g. `--limit 20`.
  2. In scripts, coerce and validate first: const n = Math.trunc(Number(v)); if (!Number.isInteger(n) || n <= 0) ...
  3. Omit the flag to use the command's default limit (e.g. 20).
  4. If the value comes from a config file, fix the entry to a plain integer string.

Example fix

// before
stackoverflow tag javascript --limit ""
// after
stackoverflow tag javascript --limit 20
Defensive patterns

Strategy: validation

Validate before calling

function toLimit(v, dflt = 20) {
  if (v == null || v === '') return dflt;
  const n = Number(v);
  if (!Number.isInteger(n) || n <= 0) throw new TypeError(`limit must be a positive integer, got ${JSON.stringify(v)}`);
  return n;
}

Type guard

function isPositiveInt(v) { return Number.isInteger(v) && v > 0; }

Try / catch

try {
  await run({ limit });
} catch (e) {
  if (e.name === 'ArgumentError' && e.message.includes('must be a positive integer')) {
    return run({ limit: 20 }); // fall back to default
  }
  throw e;
}

Prevention

When it happens

Trigger: `--limit 0`, `--limit -5`, `--limit abc`, `--limit 3.5`, `--limit ''`, or a script passing undefined combined with a non-numeric string.

Common situations: Computing a limit from user input or a config file where the value is a string like '20 ' or empty; shell passing an empty flag (`--limit=`); NaN from upstream arithmetic.

Related errors


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