yargs/yargs · error · YError

.usage() description must start with $0 if being used as ali

Error message

.usage() description must start with $0 if being used as alias for .command()

What it means

Thrown by YargsInstance.usage (lib/yargs-factory.ts:1408) when .usage(msg, description, ...) is called with a description (treating usage as an alias for .command()) but msg does not start with $0. When a description is provided, yargs interprets the call as defining a default command and requires the message to begin with $0 (the script-name placeholder); otherwise it cannot register a default command.

Source

Thrown at lib/yargs-factory.ts:1408

    msg: string | null,
    description?: CommandHandler['description'],
    builder?: CommandBuilderDefinition | CommandBuilder,
    handler?: CommandHandlerCallback
  ): YargsInstance {
    argsert(
      '<string|null|undefined> [string|boolean] [function|object] [function]',
      [msg, description, builder, handler],
      arguments.length
    );

    if (description !== undefined) {
      assertNotStrictEqual(msg, null, this.#shim);
      // .usage() can be used as an alias for defining
      // a default command.
      if ((msg || '').match(/^\$0( |$)/)) {
        return this.command(msg, description, builder, handler);
      } else {
        throw new YError(
          '.usage() description must start with $0 if being used as alias for .command()'
        );
      }
    } else {
      this.#usage.usage(msg);
      return this;
    }
  }
  usageConfiguration(config: UsageConfiguration) {
    argsert('<object>', [config], arguments.length);
    this.#usageConfig = config;
    return this;
  }
  version(opt?: string | false, msg?: string, ver?: string): YargsInstance {
    const defaultVersionOpt = 'version';
    argsert(
      '[boolean|string] [string] [string]',
      [opt, msg, ver],

View on GitHub (pinned to 34d833aab1)

Solutions

  1. Prefix the message with $0 when also passing a description: yargs.usage('$0 deploy [env]', 'Deploy the app', builder, handler).
  2. If you only want to set help/usage text, omit the description argument entirely: yargs.usage('$0 [options]').
  3. Prefer the explicit .command('$0 ...', desc, builder, handler) form to make the intent obvious.

Example fix

// before
yargs.usage('deploy [env]', 'Deploy the app', builder, handler);
// after
yargs.usage('$0 deploy [env]', 'Deploy the app', builder, handler);
Defensive patterns

Strategy: validation

Validate before calling

function safeUsage(yargs, msg, description, builder, handler) {
  if (description !== undefined && !/^\$0( |$)/.test(msg || '')) {
    throw new Error('.usage() default-command form requires msg to start with $0');
  }
  return yargs.usage(msg, description, builder, handler);
}

Type guard

function isUsageDefaultCommandForm(
  msg: unknown, description: unknown
): boolean {
  return description !== undefined && typeof msg === 'string' && /^\$0( |$)/.test(msg);
}

Try / catch

try {
  yargs.usage(msg, description, builder, handler);
} catch (e) {
  if (e instanceof Error && /usage\(\) description must start with \\$0/.test(e.message)) {
    console.error('usage-as-command requires a $0 prefix on the message');
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling yargs.usage('deploy [env]', 'Deploy the app', builder, handler) - missing the $0 prefix. Mixing the two .usage() forms: the help-text form yargs.usage('$0 [options]') (no description) and the default-command form yargs.usage('$0 deploy [env]', 'desc', builder, handler).

Common situations: Trying to define a default command via .usage() without reading the $0 convention. Refactoring from .command('$0', ...) to .usage() and dropping the $0. Copy-pasting a usage string from a help banner into a default-command definition.

Related errors


AI-assisted analysis of yargs/yargs@34d833aab1 (2026-08-03). Data as JSON: /data/errors/fe3ea9bb2d6abca0.json. Report an issue: GitHub.