tj/commander.js · error · Error

cannot add alias '${alias}' to command '${this.name()}' as a

Error message

cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'

What it means

Thrown by Command.alias() at lib/command.js:2279-2288 when adding an alias that already matches a sibling command's name or alias (scoped to this.parent's commands via _findCommand). Mirrors _registerCommand's conflict logic (error[8]) but for aliases added after the fact. The message renders the existing command's full name+aliases joined by '|' for diagnosis.

Source

Thrown at lib/command.js:2285

    // eslint-disable-next-line @typescript-eslint/no-this-alias
    let command = this;
    if (
      this.commands.length !== 0 &&
      this.commands[this.commands.length - 1]._executableHandler
    ) {
      // assume adding alias for last added executable subcommand, rather than this
      command = this.commands[this.commands.length - 1];
    }

    if (alias === command._name)
      throw new Error("Command alias can't be the same as its name");
    const matchingCommand = this.parent?._findCommand(alias);
    if (matchingCommand) {
      // c.f. _registerCommand
      const existingCmd = [matchingCommand.name()]
        .concat(matchingCommand.aliases())
        .join('|');
      throw new Error(
        `cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`,
      );
    }

    command._aliases.push(alias);
    return this;
  }

  /**
   * Set aliases for the command.
   *
   * Only the first alias is shown in the auto-generated help.
   *
   * @param {string[]} [aliases]
   * @return {(string[]|Command)}
   */

  aliases(aliases) {

View on GitHub (pinned to ba6d13ddb4)

Solutions

  1. Choose an alias that doesn't collide with any sibling command name or alias.
  2. Rename the conflicting sibling command if the alias is more important.
  3. When loading plugins/aliases dynamically, scan program.commands for existing names+aliases before calling .alias().

Example fix

// before (throws: 'run' already a sibling)
program.command('run');
program.command('start').alias('run');

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

Strategy: validation

Validate before calling

function safeAlias(parent, child, alias) {
  const taken = new Set(parent.commands.flatMap(c => [c.name(), ...c.aliases()]));
  if (taken.has(alias)) {
    throw new Error(`alias '${alias}' conflicts with existing sibling command/alias`);
  }
  child.alias(alias);
}

Prevention

When it happens

Trigger: `program.command('run'); program.command('start').alias('run')` — 'run' is already a sibling command name, so the alias collides. Also `cmd.alias('x')` when another sibling already has alias 'x'.

Common situations: Two teams adding overlapping aliases; auto-generated aliases from a config that doesn't check siblings; refactor introducing an alias that clashes with an existing command; plugin loading order making a previously-safe alias now collide.

Related errors


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