tj/commander.js · error · Error

Command passed to .addCommand() must have a name - specify t

Error message

Command passed to .addCommand() must have a name
- specify the name in Command constructor or using .name()

What it means

Thrown by Command.addCommand() at lib/command.js:290-293 when the subcommand passed in has an empty `_name`. Commander requires every registered subcommand to be addressable by name (for dispatch, help, conflict detection in _registerCommand), so a nameless Command is rejected up front.

Source

Thrown at lib/command.js:291

   */
  showSuggestionAfterError(displaySuggestion = true) {
    this._showSuggestionAfterError = !!displaySuggestion;
    return this;
  }

  /**
   * Add a prepared subcommand.
   *
   * See .command() for creating an attached subcommand which inherits settings from its parent.
   *
   * @param {Command} cmd - new subcommand
   * @param {object} [opts] - configuration options
   * @return {Command} `this` command for chaining
   */

  addCommand(cmd, opts) {
    if (!cmd._name) {
      throw new Error(`Command passed to .addCommand() must have a name
- specify the name in Command constructor or using .name()`);
    }

    opts = opts || {};
    if (opts.isDefault) this._defaultCommandName = cmd._name;
    if (opts.noHelp || opts.hidden) cmd._hidden = true; // modifying passed command due to existing implementation

    this._registerCommand(cmd);
    cmd.parent = this;
    cmd._checkForBrokenPassThrough();

    return this;
  }

  /**
   * Factory routine to create a new unattached argument.
   *
   * See .argument() for creating an attached argument, which uses this routine to

View on GitHub (pinned to ba6d13ddb4)

Solutions

  1. Pass the name in the constructor: `new Command('deploy')`.
  2. Or set it before addCommand: `cmd.name('deploy'); program.addCommand(cmd);`.
  3. If the name is derived dynamically, assert it is a non-empty string before constructing: `if (!name) throw ...`.

Example fix

// before
const sub = new Command(); // no name
program.addCommand(sub);

// after
const sub = new Command('deploy');
program.addCommand(sub);
Defensive patterns

Strategy: validation

Validate before calling

function addNamed(program, cmd) {
  if (!cmd.name?.() && !cmd._name) {
    throw new Error('Cannot add a nameless subcommand');
  }
  if (!cmd.name()) cmd.name(cmd._name || generatedName);
  return program.addCommand(cmd);
}

Type guard

import { Command } from 'commander';
function isNamedCommand(v: unknown): v is Command {
  return v instanceof Command && typeof v.name() === 'string' && v.name().length > 0;
}

Prevention

When it happens

Trigger: `new Command()` with no argument, or `new Command('')`, then `program.addCommand(cmd)`. Also happens when constructing with `.command()` style but forgetting the name, or when the name was meant to be set later via `.name()` but never was.

Common situations: Refactor where a Command was created in a factory function and the name parameter was dropped; copy-paste from `.command('name')` examples into the `new Command()` form; dynamic command construction where the name comes from a config that returned undefined.

Related errors


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