tj/commander.js · error · Error

Unexpected value for position to addHelpText. Expecting one

Error message

Unexpected value for position to addHelpText.
Expecting one of '${allowedValues.join("', '")}'

What it means

Thrown by addHelpText(position, text) when position is not one of the four allowed strings: 'beforeAll', 'before', 'after', 'afterAll'. The check is a literal includes() against that allow-list at line 2672, so any other value (wrong case, typo, synonyms like 'top'/'start') is rejected. It is a plain Error raised at registration time, before any help is ever rendered.

Source

Thrown at lib/command.js:2673

   * @property {Command} command
   * @property {function} write
   */

  /**
   * Add additional text to be displayed with the built-in help.
   *
   * Position is 'before' or 'after' to affect just this command,
   * and 'beforeAll' or 'afterAll' to affect this command and all its subcommands.
   *
   * @param {string} position - before or after built-in help
   * @param {(string | Function)} text - string to add, or a function returning a string
   * @return {Command} `this` command for chaining
   */

  addHelpText(position, text) {
    const allowedValues = ['beforeAll', 'before', 'after', 'afterAll'];
    if (!allowedValues.includes(position)) {
      throw new Error(`Unexpected value for position to addHelpText.
Expecting one of '${allowedValues.join("', '")}'`);
    }

    const helpEvent = `${position}Help`;
    this.on(helpEvent, (/** @type {HelpTextEventContext} */ context) => {
      let helpStr;
      if (typeof text === 'function') {
        helpStr = text({ error: context.error, command: context.command });
      } else {
        helpStr = text;
      }
      // Ignore falsy value when nothing to output.
      if (helpStr) {
        context.write(`${helpStr}\n`);
      }
    });
    return this;
  }

View on GitHub (pinned to ba6d13ddb4)

Solutions

  1. Use exactly one of: 'beforeAll', 'before', 'after', 'afterAll' (case-sensitive).
  2. If the position comes from config, validate it against the allow-list before calling addHelpText.
  3. For text above all commands use 'beforeAll'; for text after everything use 'afterAll'; for a single command use 'before'/'after'.

Example fix

// before
program.addHelpText('top', 'My Tool v2.0');

// after
program.addHelpText('beforeAll', 'My Tool v2.0');
Defensive patterns

Strategy: validation

Validate before calling

const HELP_POSITIONS = ['beforeAll', 'before', 'after', 'afterAll'];
function addHelpTextSafe(cmd, position, text) {
  if (!HELP_POSITIONS.includes(position)) {
    throw new Error(
      `addHelpText position must be one of ${HELP_POSITIONS.join(', ')} (got ${JSON.stringify(position)})`
    );
  }
  return cmd.addHelpText(position, text);
}

Type guard

const HELP_POSITIONS = ['beforeAll', 'before', 'after', 'afterAll'];
function isHelpPosition(v) {
  return typeof v === 'string' && HELP_POSITIONS.includes(v);
}

Prevention

When it happens

Trigger: Calling program.addHelpText('top', '...'), program.addHelpText('Before', '...') (wrong case), program.addHelpText('start', '...'), or passing a value computed from config/variable that does not exactly match one of the four allowed positions.

Common situations: Typos or inconsistent casing ('afterall' vs 'afterAll'); guessing a position name instead of checking the docs; driving addHelpText from a user-supplied config key; copy-paste from a different CLI library that uses different position names.

Related errors


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