tj/commander.js · error · InvalidArgumentError
Allowed choices are ${this.argChoices.join(', ')}.
Error message
Allowed choices are ${this.argChoices.join(', ')}. What it means
Thrown by Argument.choices() (lib/argument.js:100-105) when an argument value is not in the configured allow-list. The choices() method installs a parseArg that calls Array.includes on this.argChoices; a miss throws InvalidArgumentError listing the allowed values. This is the argument-side analogue of option choices.
Source
Thrown at lib/argument.js:102
*/
argParser(fn) {
this.parseArg = fn;
return this;
}
/**
* Only allow argument value to be one of choices.
*
* @param {string[]} values
* @return {Argument}
*/
choices(values) {
this.argChoices = values.slice();
this.parseArg = (arg, previous) => {
if (!this.argChoices.includes(arg)) {
throw new InvalidArgumentError(
`Allowed choices are ${this.argChoices.join(', ')}.`,
);
}
if (this.variadic) {
return this._collectValue(arg, previous);
}
return arg;
};
return this;
}
/**
* Make argument required.
*
* @returns {Argument}
*/
argRequired() {
this.required = true;View on GitHub (pinned to ba6d13ddb4)
Solutions
- Pass one of the listed allowed values.
- If the value should be valid, add it to the choices() array.
- Normalize input case before choices() — e.g. `.choices(['a','b'])` plus a parser that lowercases — or call choices with the full set including upper-case variants.
- Surface the allowed set in --help by describing it in the argument description string.
Example fix
// before
.argument('<mode>', 'mode').choices(['read', 'write'])
// prog READ -> throws
// after
.argument('<mode>', 'mode', (v) => v.toLowerCase()).choices(['read', 'write']) Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = ['read', 'write', 'append'];
const value = process.argv[idx];
if (!ALLOWED.includes(value)) {
console.error(`mode must be one of: ${ALLOWED.join(', ')}`);
process.exit(2);
} Type guard
const MODES = ['read', 'write', 'append'] as const;
type Mode = typeof MODES[number];
function isMode(v: unknown): v is Mode {
return typeof v === 'string' && (MODES as readonly string[]).includes(v);
} Try / catch
try { await program.parseAsync(); }
catch (e) {
if (e.code === 'commander.invalidArgument' && /Allowed choices/.test(e.message)) {
console.error(e.message); process.exit(2);
}
throw e;
} Prevention
- Derive the choices array from a single shared const so help, validation, and TS types stay in sync.
- Normalize case before choices() if users commonly vary capitalization.
- Echo the allowed set in the argument description for --help.
When it happens
Trigger: Calling `.argument('<mode>', 'mode', null).choices(['a','b','c'])` then running the program with a value outside ['a','b','c'], e.g. `prog d`. Each variadic value is checked individually, so `prog a x b` also fails on 'x'.
Common situations: Typos in the supplied value; case mismatch ('A' vs 'a' — choices is case-sensitive); a new valid choice added to the backend but not to the choices() list; upstream script forwarding an unfiltered env value.
Related errors
- Not a number.
- Not a number.
- Allowed choices are ${this.argChoices.join(', ')}.
- '${executableFile}' does not exist - if '${subcommandName}'
- Command alias can't be the same as its name
AI-assisted analysis of tj/commander.js@ba6d13ddb4 (2026-08-03).
Data as JSON: /data/errors/378cc8ef232b453c.json.
Report an issue: GitHub.