Skip to content

parseArgs: --help and --version silently accept extra positional arguments #88

@joewalker

Description

@joewalker

Observed behavior

parseArgs short-circuits when either --help or --version is present and returns immediately, before the positional.length > 1 check that was added to reject extra positional arguments (see #33). As a result:

parseArgs(['--help'])                       -> { help: true, ... }   (OK)
parseArgs(['--help', 'foo', 'bar'])         -> { help: true, ... }   (silently ignores foo, bar)
parseArgs(['--version', 'extra1', 'extra2']) -> { version: true, ... } (silently ignores extras)
parseArgs(['config.json', 'extra'])         -> THROW: Unexpected extra arguments: extra  (correct)

The relevant block in parseArgs:

if (booleans.help || booleans.version) {
  return {
    help: booleans.help,
    version: booleans.version,
    verbose: booleans.verbose,
    dryRun: booleans.dryRun,
    maxPrompts,
  };
}

if (positional.length > 1) {
  throw new Error(
    `Unexpected extra arguments: ${positional.slice(1).join(' ')}`,
  );
}

Expected behavior

For consistency with #33's fix, --help and --version should also reject extra positional arguments (or at least reject anything beyond a single positional). Silent acceptance hides typos like loop-the-loop --help confg.json and is inconsistent with the rest of the parser's strictness.

Minimal reproduction

parseArgs(['--help', 'foo', 'bar']);
// Returns { help: true, ... } with no warning that 'foo' and 'bar' were dropped.

Suggested fix

Move the positional.length > 1 check (or a positional.length > 0 check for the help/version branch) above the help/version short-circuit, or duplicate it inside the branch. For example:

if (booleans.help || booleans.version) {
  if (positional.length > 0) {
    throw new Error(
      `Unexpected extra arguments: ${positional.join(' ')}`,
    );
  }
  return { help: booleans.help, version: booleans.version, ... };
}

This mirrors how the parser already treats trailing args after a config path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    S4Clean-ups or nits with low behavioral riskbugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions