jackwener/OpenCLI · error · ArgumentError

${label} must be a non-negative integer, got ${JSON.stringif

Error message

${label} must be a non-negative integer, got ${JSON.stringify(value)}

What it means

requireNonNegativeInteger validates a numeric CLI argument (falling back to defaultValue when null/undefined) and throws an ArgumentError from the shared search adapter when the value is not an integer or is negative. The message includes the JSON-stringified original value so you can see exactly what was passed. It guards helpers like page-size/offset parameters in browser-backed search commands.

Source

Thrown at clis/_shared/search-adapter.js:27

}

export function requireBoundedInteger(value, defaultValue, min, max, label) {
  const raw = value ?? defaultValue;
  const parsed = typeof raw === 'number' ? raw : Number(raw);
  if (!Number.isInteger(parsed)) {
    throw new ArgumentError(`${label} must be an integer between ${min} and ${max}, got ${JSON.stringify(value)}`);
  }
  if (parsed < min || parsed > max) {
    throw new ArgumentError(`${label} must be between ${min} and ${max}, got ${parsed}`);
  }
  return parsed;
}

export function requireNonNegativeInteger(value, defaultValue, label) {
  const raw = value ?? defaultValue;
  const parsed = typeof raw === 'number' ? raw : Number(raw);
  if (!Number.isInteger(parsed) || parsed < 0) {
    throw new ArgumentError(`${label} must be a non-negative integer, got ${JSON.stringify(value)}`);
  }
  return parsed;
}

export function unwrapBrowserResult(value) {
  if (value && typeof value === 'object' && !Array.isArray(value) && 'session' in value && 'data' in value) {
    return value.data;
  }
  return value;
}

export function requireRows(value, label) {
  const rows = unwrapBrowserResult(value);
  if (!Array.isArray(rows)) {
    throw new CommandExecutionError(`${label} returned an unexpected payload shape; expected an array of result rows.`);
  }
  return rows;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a whole non-negative integer for the flagged argument (check the command's --help for valid values).
  2. If omitting the flag is acceptable, drop it so the defaultValue is used.
  3. If you pass the value programmatically, coerce/validate first: Number.isInteger(Number(v)) && Number(v) >= 0.
  4. Quote the value in shell to avoid stray characters being split into the flag.

Example fix

// before
opencli mysearch results --limit -5
// after
opencli mysearch results --limit 10
Defensive patterns

Strategy: validation

Validate before calling

function isValidLimit(v) {
  const n = Number(v);
  return Number.isInteger(n) && n >= 0;
}
if (!isValidLimit(myArg)) throw new Error('limit must be a non-negative integer');

Type guard

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

Try / catch

try {
  await runCommand(['mysearch', 'results', '--limit', String(n)]);
} catch (e) {
  if (e instanceof ArgumentError && /non-negative integer/.test(e.message)) {
    console.error('Bad --limit value; using default.');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling a search CLI command with a negative number (e.g. --limit -1), a non-numeric string (e.g. --limit 'abc'), or a float (e.g. --offset 2.5) where requireNonNegativeInteger is used as the arg validator.

Common situations: Copy-pasted flags with stray characters (e.g. '--limit 10,'), shell scripts interpolating empty or malformed variables into the flag, units accidentally included ('--limit 20px'), and scripts using 0-based negatives from elsewhere.

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