jackwener/OpenCLI · error · ArgumentError

${label} must be one of: ${Object.keys(choices).join(', ')}

Error message

${label} must be one of: ${Object.keys(choices).join(', ')}

What it means

normalizeChoice validates an option against a fixed set of allowed keys (used for eventType, ranking, map, version options). It throws when the stringified value is not one of the accepted choices, listing all valid keys in the message.

Source

Thrown at clis/hltv/utils.js:82

  const raw = value ?? defaultValue;
  const n = Number(raw);
  if (!Number.isInteger(n) || n <= 0) throw new ArgumentError(`${label} must be a positive integer`);
  if (n > maxValue) throw new ArgumentError(`${label} must be <= ${maxValue}`);
  return n;
}

export function normalizeOffset(value, defaultValue = 0) {
  const raw = value ?? defaultValue;
  const n = Number(raw);
  if (!Number.isInteger(n) || n < 0) throw new ArgumentError('offset must be a non-negative integer');
  if (n % 100 !== 0) throw new ArgumentError('offset must be a multiple of 100');
  return n;
}

export function normalizeChoice(value, defaultValue, choices, label) {
  const raw = String(value ?? defaultValue);
  if (!Object.prototype.hasOwnProperty.call(choices, raw)) {
    throw new ArgumentError(`${label} must be one of: ${Object.keys(choices).join(', ')}`);
  }
  return raw;
}

export function parseNumber(value) {
  const raw = String(value ?? '').replace(/\s+/g, ' ').trim();
  if (!raw || raw === '-' || raw.toLowerCase() === 'n/a') return null;
  const match = raw.replace(/,/g, '').match(/-?\d+(?:\.\d+)?/);
  if (!match) return null;
  const n = Number(match[0]);
  return Number.isFinite(n) ? n : null;
}

export function parseMoneyUsd(value) {
  return parseNumber(String(value ?? '').replace(/\$/g, ''));
}

export function absolutizeUrl(value) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use one of the exact keys printed in the error message
  2. Run the command with --help to see the accepted choices for that option
  3. Check the library's CHANGELOG in case the option key was renamed between versions

Example fix

// before
hltv maps --map de_dust2
// after
hltv maps --map dust2  # use a key from the allowed list
Defensive patterns

Strategy: validation

Validate before calling

const MAPS = ['mirage','inferno','nuke','overpass','vertigo','ancient','anubis','dust2','train'];
if (opts.map && !MAPS.includes(String(opts.map).toLowerCase())) throw new Error(`map must be one of: ${MAPS.join(', ')}`);

Type guard

const isChoice = (v, choices) => Object.prototype.hasOwnProperty.call(choices, String(v));

Try / catch

try {
  await hltv.stats({ map: opts.map });
} catch (e) {
  if (e.name === 'ArgumentError' && e.message.startsWith('map must be one of')) {
    console.error(e.message); // message lists valid keys
    process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Passing an unknown value like --map cache or --event-type lan when the mapping only defines specific keys; typos or casing differences; renamed options after a library update.

Common situations: Old scripts using choice keys removed in a newer version; guessing slug-style names instead of the exact keys; copy-pasting values from HLTV's UI rather than this CLI's list.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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