tj/commander.js · error · Error

cannot add command '${newCmd}' as already have command '${ex

Error message

cannot add command '${newCmd}' as already have command '${existingCmd}'

What it means

Thrown by Command._registerCommand() at lib/command.js:645-659 when a command (or any of its aliases) collides with an already-registered command's name or aliases. The check uses knownBy() = [name, ...aliases] on both sides, and the message renders the full alias set joined by '|' so you can see exactly what clashed.

Source

Thrown at lib/command.js:656

   * 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());
    };

    const alreadyUsed = knownBy(command).find((name) =>
      this._findCommand(name),
    );
    if (alreadyUsed) {
      const existingCmd = knownBy(this._findCommand(alreadyUsed)).join('|');
      const newCmd = knownBy(command).join('|');
      throw new Error(
        `cannot add command '${newCmd}' as already have command '${existingCmd}'`,
      );
    }

    this._initCommandGroup(command);
    this.commands.push(command);
  }

  /**
   * Add an option.
   *
   * @param {Option} option
   * @return {Command} `this` command for chaining
   */
  addOption(option) {
    this._registerOption(option);

    const oname = option.name();

View on GitHub (pinned to ba6d13ddb4)

Solutions

  1. Rename the second command, or remove the duplicate registration.
  2. Audit aliases — change the alias so it doesn't collide with a sibling command name.
  3. When auto-discovering subcommands, deduplicate by name/alias before calling addCommand, and log a warning on skip.

Example fix

// before (throws: 'run' collides)
program.command('run').alias('start');
program.command('start');

// after
program.command('run').alias('launch');
program.command('start');
Defensive patterns

Strategy: validation

Validate before calling

function safeAddCommand(parent, cmd) {
  const taken = new Set(parent.commands.flatMap(c => [c.name(), ...c.aliases()]));
  const novel = [cmd.name(), ...cmd.aliases()].filter(n => taken.has(n));
  if (novel.length) throw new Error(`command name/alias conflict: ${novel.join(', ')}`);
  return parent.addCommand(cmd);
}

Prevention

When it happens

Trigger: Two `program.command('build')` declarations; adding `cmd1.alias('run')` then `cmd2` named 'run'; addCommand of a subcommand whose alias matches an existing subcommand's name. Each registration re-runs the conflict scan against this.commands.

Common situations: Loading subcommands from a directory where two files resolve to the same name; merging command sets from plugins; an alias that accidentally equals a sibling command's name; refactor that renamed a command but left the old registration in place.

Related errors


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