jackwener/OpenCLI · error · ArgumentError

steam ${label} must be a positive integer

Error message

steam ${label} must be a positive integer

What it means

requireBoundedInt coerces its input to a number and requires a positive integer; anything else (floats, zero, negatives, non-numeric strings, NaN) throws ArgumentError. It protects numeric options like limit from bad input.

Source

Thrown at clis/steam/utils.js:32

}

export function requireCountryCode(value, defaultValue = 'us') {
    const raw = value === undefined || value === null ? defaultValue : value;
    const code = String(raw).trim().toLowerCase();
    if (!/^[a-z]{2}$/.test(code)) {
        throw new ArgumentError(
            `steam currency must be a two-letter storefront country code (got "${value}")`,
            'Examples: us, cn, jp, de. This controls Steam regional pricing and availability.',
        );
    }
    return code;
}

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(`steam ${label} must be a positive integer`);
    }
    if (n > maxValue) {
        throw new ArgumentError(`steam ${label} must be <= ${maxValue}`);
    }
    return n;
}

export function requireAppId(value) {
    const s = String(value ?? '').trim();
    if (!s) {
        throw new ArgumentError('steam app id is required (e.g. "620" for Portal 2)');
    }
    if (!/^\d+$/.test(s)) {
        throw new ArgumentError(
            `steam app id "${value}" must be a positive integer`,
            'Copy the numeric id from `steam search` or the URL `store.steampowered.com/app/<id>/`.',
        );
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a positive integer value for the option (e.g. --limit 20)
  2. Pre-parse and validate numeric flags before calling the command
  3. Ensure empty strings are converted to undefined so the default is used
  4. Catch ArgumentError to display correct flag usage

Example fix

// before
--limit ""   // Number("") === 0 → ArgumentError
// after
--limit 20
Defensive patterns

Strategy: validation

Validate before calling

function asPositiveInt(v) {
  const n = typeof v === 'number' ? v : Number(String(v ?? '').trim());
  if (!Number.isInteger(n) || n <= 0) throw new Error(`expected positive integer, got: ${v}`);
  return n;
}

Type guard

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

Try / catch

try {
  await cmd({ limit: raw });
} catch (e) {
  if (e instanceof ArgumentError && /must be a positive integer/.test(e.message)) {
    console.error('Pass an integer like --limit 20');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing --limit 0, --limit -5, --limit abc, --limit 12.5, or an empty string that coerces to NaN; default path is fine because the default is applied when value is undefined/null.

Common situations: Users passing 'all' or blank values to a limit flag; shell variables that are unset producing empty strings; JSON config carrying null → default applies, but "" does not.

Related errors


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