jackwener/OpenCLI · error · ArgumentError

--${name} must be an integer between 1 and ${max}

Error message

--${name} must be an integer between 1 and ${max}

What it means

requireBoundedInt coerces an option to a number and enforces that it is an integer within [1, max] (defaults applied when empty), throwing ArgumentError otherwise. It protects the openFDA API from invalid limit values that would be rejected server-side. The message names the flag and the allowed range.

Source

Thrown at clis/openfda/utils.js:21

// Free public tier with anonymous rate limit (~240 req/min, 1000 req/day per IP).
// API key bumps that to 240 req/min × ~120000 req/day, but is not required for
// modest read traffic.
import { ArgumentError, EmptyResultError, CommandExecutionError } from '@jackwener/opencli/errors';

export const OPENFDA_BASE = 'https://api.fda.gov';
const UA = 'opencli-openfda/1.0';

export function requireString(value, name) {
    if (typeof value !== 'string' || !value.trim()) {
        throw new ArgumentError(`--${name} is required`);
    }
    return value.trim();
}

export function requireBoundedInt(value, def, max, name = 'limit') {
    const n = value == null || value === '' ? def : Number(value);
    if (!Number.isInteger(n) || n < 1 || n > max) {
        throw new ArgumentError(`--${name} must be an integer between 1 and ${max}`);
    }
    return n;
}

export async function openfdaFetch(url, label) {
    let resp;
    try {
        resp = await fetch(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });
    } catch (err) {
        throw new CommandExecutionError(`${label} request failed: ${err.message}`);
    }
    if (resp.status === 404) {
        // openFDA returns 404 for "no matches" instead of an empty results array.
        throw new EmptyResultError(label, `${label} returned 404 (no matches).`);
    }
    if (resp.status === 429) {
        throw new CommandExecutionError(`${label} rate-limited (HTTP 429); back off and retry.`);
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Set --limit to an integer between 1 and the endpoint's max (openFDA caps at 1000; the CLI enforces its own max).
  2. Omit the flag entirely to use the built-in default.
  3. In scripts, validate/round the number before passing: limit=Math.min(1000, Math.max(1, Math.trunc(n))).
  4. Check the CLI's --help for the accepted range.

Example fix

// before
opencli openfda food-recall --limit 0        # throws
// after
opencli openfda food-recall --limit 25
Defensive patterns

Strategy: validation

Validate before calling

function ensureBoundedLimit(value, max = 1000, def = 10) {
  const n = value == null || value === '' ? def : Number(value);
  if (!Number.isInteger(n) || n < 1 || n > max) {
    throw new Error(`--limit must be an integer between 1 and ${max}`);
  }
  return n;
}

Type guard

function isBoundedInt(v, max) {
  const n = Number(v);
  return Number.isInteger(n) && n >= 1 && n <= max;
}

Try / catch

try {
  const rows = await fetchFoodRecalls({ limit });
} catch (e) {
  if (e instanceof ArgumentError && /must be an integer/.test(e.message)) {
    console.error(`${e.message} — try --limit 25`);
    process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Passing --limit 0, a negative number, a non-integer like 2.5, a non-numeric string like 'ten', or a value above the endpoint max (e.g. --limit 5000). Empty/null falls back to the default and does not throw.

Common situations: User assumes the limit is unbounded and asks for thousands of rows; a script passes a float computed from arithmetic; a typo like '--limit 1oo' is coerced to NaN; confusing 1-based vs 0-based bounds.

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