{"id":"9a3421478cc32153","repo":"tj/commander.js","slug":"cannot-add-command-newcmd-as-already-have-com","errorCode":null,"errorMessage":"cannot add command '${newCmd}' as already have command '${existingCmd}'","messagePattern":"cannot add command '(.+?)' as already have command '(.+?)'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/command.js","lineNumber":656,"sourceCode":"   * Check for command name and alias conflicts with existing commands.\n   * Register command if no conflicts found, or throw on conflict.\n   *\n   * @param {Command} command\n   * @private\n   */\n\n  _registerCommand(command) {\n    const knownBy = (cmd) => {\n      return [cmd.name()].concat(cmd.aliases());\n    };\n\n    const alreadyUsed = knownBy(command).find((name) =>\n      this._findCommand(name),\n    );\n    if (alreadyUsed) {\n      const existingCmd = knownBy(this._findCommand(alreadyUsed)).join('|');\n      const newCmd = knownBy(command).join('|');\n      throw new Error(\n        `cannot add command '${newCmd}' as already have command '${existingCmd}'`,\n      );\n    }\n\n    this._initCommandGroup(command);\n    this.commands.push(command);\n  }\n\n  /**\n   * Add an option.\n   *\n   * @param {Option} option\n   * @return {Command} `this` command for chaining\n   */\n  addOption(option) {\n    this._registerOption(option);\n\n    const oname = option.name();","sourceCodeStart":638,"sourceCodeEnd":674,"githubUrl":"https://github.com/tj/commander.js/blob/ba6d13ddb4243e5913367734f8c159089ffe7834/lib/command.js#L638-L674","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename the second command, or remove the duplicate registration.","Audit aliases — change the alias so it doesn't collide with a sibling command name.","When auto-discovering subcommands, deduplicate by name/alias before calling addCommand, and log a warning on skip."],"exampleFix":"// before (throws: 'run' collides)\nprogram.command('run').alias('start');\nprogram.command('start');\n\n// after\nprogram.command('run').alias('launch');\nprogram.command('start');","handlingStrategy":"validation","validationCode":"function safeAddCommand(parent, cmd) {\n  const taken = new Set(parent.commands.flatMap(c => [c.name(), ...c.aliases()]));\n  const novel = [cmd.name(), ...cmd.aliases()].filter(n => taken.has(n));\n  if (novel.length) throw new Error(`command name/alias conflict: ${novel.join(', ')}`);\n  return parent.addCommand(cmd);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Maintain a registry/const of command names and aliases for your app.","When auto-discovering subcommands, dedupe by name+aliases before registering.","Audit aliases whenever you rename a command."],"tags":["commander","subcommand","conflict","alias","configuration"],"analyzedSha":"ba6d13ddb4243e5913367734f8c159089ffe7834","analyzedAt":"2026-08-03T20:26:04.326Z","schemaVersion":2}