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

  1. Rename one of the conflicting flags (short or long) so they are unique on the command.
  2. If both options are the same concept, delete the duplicate declaration.
  3. 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

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


AI-assisted analysis of tj/commander.js@ba6d13ddb4 (2026-08-03). Data as JSON: /data/errors/b83dc232ba955c1f.json. Report an issue: GitHub.