jackwener/OpenCLI · error · ArgumentError

rest-countries ${label} must be a positive integer

Error message

rest-countries ${label} must be a positive integer

What it means

requireBoundedInt coerces its input to a number and throws ArgumentError if the result is not a positive integer. This catches NaN, floats, zero, negatives, and non-numeric strings. It exists so the limit argument is always a sane count before building API requests.

Source

Thrown at clis/rest-countries/utils.js:32

// Fields the adapter always requests; keep this list aligned with `columns` so
// rows never have null-where-absent silent drops.
export const COUNTRY_FIELDS = [
    'name', 'cca2', 'cca3', 'ccn3', 'capital', 'region', 'subregion',
    'population', 'area', 'languages', 'currencies', 'flag', 'latlng', 'timezones',
    'independent', 'unMember', 'landlocked',
].join(',');

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

export function requireRegion(value) {
    const raw = String(value ?? '').trim().toLowerCase();
    if (!raw) throw new ArgumentError('rest-countries region is required (e.g. "europe", "asia")');
    if (!REST_COUNTRIES_REGIONS.has(raw)) {
        throw new ArgumentError(
            `rest-countries region "${value}" is not recognised`,
            `Allowed regions: ${[...REST_COUNTRIES_REGIONS].join(', ')}.`,
        );
    }
    return raw;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass limit as a positive whole number (>= 1).
  2. Coerce and validate the value (Number.isInteger) before calling the command.
  3. Omit limit to use the command's default.
  4. Catch ArgumentError and re-prompt or fall back to the default.

Example fix

// before
await countryCommand({ name: 'france', limit: 'ten' });
// after
await countryCommand({ name: 'france', limit: 10 });
Defensive patterns

Strategy: validation

Validate before calling

const n = Number(rawLimit);
if (!Number.isInteger(n) || n <= 0) {
  throw new TypeError('limit must be a positive integer');
}

Type guard

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

Try / catch

try {
  await countryCommand({ name, limit: rawLimit });
} catch (err) {
  if (err instanceof ArgumentError && /positive integer/.test(err.message)) {
    return countryCommand({ name }); // fall back to default limit
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing limit values like 0, -5, 'abc', 2.5, or '' to a rest-countries command so `Number.isInteger(n) || n <= 0` fails at clis/rest-countries/utils.js:32.

Common situations: User typing a non-numeric CLI flag value; a config file containing '25 countries'; floating-point math producing a fractional limit; empty string from an unset env var.

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/cdf8ec7a6d35bc62. Report an issue: GitHub.