tj/commander.js · error · Error
Cannot add option '${option.flags}'${this._name && ` to comm
Error message
Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'
- already used by option '${matchingOption.flags}' What it means
Thrown by Command._registerOption() at lib/command.js:620-631 when a new option's short or long flag already matches an option registered on the same command. Commander keys options by flag for dispatch (the `on('option:'+oname)` listener) and for --help grouping, so duplicates would silently shadow each other.
Source
Thrown at lib/command.js:629
/**
* Check for option flag conflicts.
* Register option if no conflicts found, or throw on conflict.
*
* @param {Option} option
* @private
*/
_registerOption(option) {
const matchingOption =
(option.short && this._findOption(option.short)) ||
(option.long && this._findOption(option.long));
if (matchingOption) {
const matchingFlag =
option.long && this._findOption(option.long)
? option.long
: option.short;
throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'
- already used by option '${matchingOption.flags}'`);
}
this._initOptionGroup(option);
this.options.push(option);
}
/**
* Check for command name and alias conflicts with existing commands.
* Register command if no conflicts found, or throw on conflict.
*
* @param {Command} command
* @private
*/
_registerCommand(command) {
const knownBy = (cmd) => {
return [cmd.name()].concat(cmd.aliases());View on GitHub (pinned to ba6d13ddb4)
Solutions
- Rename one of the conflicting flags (short or long) so they are unique on the command.
- If both options are the same concept, delete the duplicate declaration.
- Centralize option definitions in one module and assert uniqueness before registering, especially when assembling commands programmatically.
Example fix
// before (throws: -v used twice)
.option('-v, --verbose', 'verbosity')
.option('-v, --version', 'show version')
// after
.option('-v, --verbose', 'verbosity')
.option('-V, --version', 'show version') Defensive patterns
Strategy: validation
Validate before calling
function registerOptions(cmd, options) {
const seen = new Set();
for (const opt of options) {
for (const flag of [opt.short, opt.long].filter(Boolean)) {
if (seen.has(flag)) throw new Error(`duplicate flag ${flag}`);
seen.add(flag);
}
cmd.addOption(opt);
}
} Type guard
import { Option } from 'commander';
function hasUniqueFlags(opts: Option[]): boolean {
const seen = new Set<string>();
return opts.every(o => [o.short, o.long].filter(Boolean).every(f => !seen.has(f) && (seen.add(f), true)));
} Prevention
- Centralize option definitions to avoid cross-module collisions.
- When merging commands from plugins, scan existing flags first.
- Use distinct short flags for sibling commands (avoid universal -v/-h clashes).
When it happens
Trigger: Two `.option('-v, --verbose')` calls on the same program; or `-v, --verbose` followed by `-v, --version` (shared `-v`); or adding an option whose `--long` collides with an existing one. The error identifies both the new flags and the conflicting existing option.
Common situations: Composing options from multiple modules/helpers that each define `-v`/`--verbose`; renaming an option but forgetting to remove the old declaration; merging two CLIs; auto-generated options that don't check for collisions.
Related errors
- cannot add command '${newCmd}' as already have command '${ex
- To add an Option object use addOption() instead of option()
- cannot add alias '${alias}' to command '${this.name()}' as a
- Command passed to .addCommand() must have a name - specify t
- only the last argument can be variadic '${previousArgument.n
AI-assisted analysis of tj/commander.js@ba6d13ddb4 (2026-08-03).
Data as JSON: /data/errors/b83dc232ba955c1f.json.
Report an issue: GitHub.