tj/commander.js · error · InvalidArgumentError

Not a number.

Error message

Not a number.

What it means

Thrown by a custom argument parser supplied via Argument.argParser (or the third argument to .argument()) when the user-supplied command-line value fails validation. In the example at examples/arguments-custom-processing.js:14, myParseInt calls parseInt(value, 10) and throws InvalidArgumentError('Not a number.') when the result is NaN. It is an InvalidArgumentError (code 'commander.invalidArgument'), so Commander formats it as a user-facing CLI error rather than a crash, and exits with code 1.

Source

Thrown at examples/arguments-custom-processing.js:14

#!/usr/bin/env node

// This is used as an example in the README for:
//    Custom argument processing
//    You may specify a function to do custom processing of argument values.

import { Command, InvalidArgumentError } from 'commander';
const program = new Command();

function myParseInt(value) {
  // parseInt takes a string and a radix
  const parsedValue = parseInt(value, 10);
  if (isNaN(parsedValue)) {
    throw new InvalidArgumentError('Not a number.');
  }
  return parsedValue;
}

// The previous value passed to the custom processing is used when processing variadic values.
function mySum(value, total) {
  return total + myParseInt(value);
}

program
  .command('add')
  .argument('<first>', 'integer argument', myParseInt)
  .argument('[second]', 'integer argument', myParseInt, 1000)
  .action((first, second) => {
    console.log(`${first} + ${second} = ${first + second}`);
  });

program

View on GitHub (pinned to ba6d13ddb4)

Solutions

  1. Pass a valid integer on the command line, e.g. `add 12 56` instead of `add twelve`.
  2. If non-integer input is legitimate, loosen the parser — replace parseInt with Number or parseFloat and widen the isNaN check, or use a regex to strip units before parsing.
  3. Add a friendlier message: `throw new InvalidArgumentError('Expected an integer, got: ' + value);` so the end user knows what to fix.
  4. If empty strings are expected, guard with `if (value === '') return defaultValue;` before parsing.

Example fix

// before
function myParseInt(value) {
  const parsedValue = parseInt(value, 10);
  if (isNaN(parsedValue)) {
    throw new InvalidArgumentError('Not a number.');
  }
  return parsedValue;
}

// after
function myParseInt(value) {
  const parsedValue = parseInt(value, 10);
  if (isNaN(parsedValue)) {
    throw new InvalidArgumentError(`Expected an integer, got: '${value}'`);
  }
  return parsedValue;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate before relying on the value
function isValidInt(v) {
  return typeof v === 'string' && /^-?\d+$/.test(v);
}
if (!isValidInt(rawInput)) {
  console.error(`Expected integer, got: ${rawInput}`);
  process.exit(1);
}

Type guard

function isIntString(v: unknown): v is string {
  return typeof v === 'string' && /^-?\d+$/.test(v);
}

Try / catch

// Wrap the parser so a bad value is reported, not fatal
try {
  program.parseAsync();
} catch (e) {
  if (e.code === 'commander.invalidArgument') {
    console.error(e.message);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `node arguments-custom-processing add foo` (or `sum silly`) where the `<first>` / `[second]` / `<value...>` argument cannot be parsed by myParseInt. Any string that yields NaN under parseInt(_, 10) — e.g. 'abc', '', '1.2.3' — trips the `isNaN` branch at line 13 and re-throws as InvalidArgumentError at line 14.

Common situations: User pastes a value with a unit suffix ('10px'), passes a flag-like token that gets captured as the argument, or a wrapper script forwards an env var that happens to be empty/non-numeric. Also occurs when the radix assumption (base 10) silently rejects hex/scientific input like '0x1F' or '1e2'.

Related errors


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