jackwener/OpenCLI · error · ArgumentError

${label} must be a non-negative integer

Error message

${label} must be a non-negative integer

What it means

normalizeNonNegativeInt requires its input to coerce (via Number()) to an integer that is 0 or greater. This ArgumentError is thrown for options like children or offset when the value is non-numeric, fractional, or negative. Zero is explicitly allowed here, unlike the positive-int variant.

Source

Thrown at clis/booking/search.js:26

const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;

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

function normalizeNonNegativeInt(value, defaultValue, label, max) {
  const raw = value ?? defaultValue;
  const n = Number(raw);
  if (!Number.isInteger(n) || n < 0) {
    throw new ArgumentError(`${label} must be a non-negative integer`);
  }
  if (typeof max === 'number' && n > max) {
    throw new ArgumentError(`${label} must be <= ${max}`);
  }
  return n;
}

function normalizeDate(value, label) {
  const v = String(value || '').trim();
  if (!v) {
    throw new ArgumentError(`${label} is required (YYYY-MM-DD)`);
  }
  if (!DATE_RE.test(v)) {
    throw new ArgumentError(`${label} must be YYYY-MM-DD, got ${JSON.stringify(value)}`);
  }
  const [year, month, day] = v.split('-').map(Number);
  const d = new Date(Date.UTC(year, month - 1, day));
  if (

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a whole number >= 0 for the flagged option (e.g. --children 0, --offset 0).
  2. Validate input before the call: Number.isInteger(n) && n >= 0.
  3. Omit the option so the built-in defaultValue applies instead of passing a bad sentinel like -1.
  4. Fix the upstream calculation producing the negative value (e.g. clamp page index to 0).

Example fix

// before
const offset = (page - 1) * size; // page=0 -> offset=-20
await bookingSearch({ offset }); // throws: offset must be a non-negative integer
// after
const offset = Math.max(0, (page - 1) * size);
await bookingSearch({ offset });
Defensive patterns

Strategy: validation

Validate before calling

function assertNonNegativeInt(value, label, max) {
  const n = Number(value);
  if (!Number.isInteger(n) || n < 0) throw new Error(`${label} must be a non-negative integer`);
  if (typeof max === 'number' && n > max) throw new Error(`${label} must be <= ${max}`);
  return n;
}
const offset = assertNonNegativeInt(opts.offset ?? 0, 'offset');

Type guard

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

Try / catch

try {
  await bookingSearch({ children, offset });
} catch (e) {
  if (e instanceof ArgumentError && e.message.includes('must be a non-negative integer')) {
    console.error(`Bad numeric option: ${e.message}`); process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Passing children: -1, offset: -10, children: 'none', offset: 1.5, or an empty string to search. Also passing undefined when no defaultValue exists for that option.

Common situations: Computing offset as currentPage*size with currentPage initialized to -1; form inputs left as '-' or blank strings submitted programmatically; typos like '--children -0.5'; passing NaN from a failed parseInt without a radix/fallback.

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