# Missing argument handling

- **Pattern:** `ab-000653` (`cli-quality.error-handling.missing-arg-handling`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000653
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000653)

## Why it matters

When a required argument is silently missing, the command either crashes mid-execution with a raw `TypeError: Cannot read properties of undefined` — dumping a stack trace onto the user — or it runs with `undefined` as a value and produces silent corruption downstream (a deploy target of `undefined`, a file named `undefined.json`, a database query with a null key). CWE-233 (Improper Handling of Parameters) applies: the input is invalid, but no validation gate catches it before execution begins. ISO 25010:2011 usability.learnability penalizes CLIs that make users guess what went wrong — the error message must name the missing argument and show the correct usage.

## Severity rationale

High because missing required arguments that produce TypeErrors or silent `undefined` behavior give users no actionable path to recovery without reading source code.

## Remediation

Use the framework's native required-argument syntax so validation happens before your handler runs. In commander, angle brackets mark required arguments:

```ts
program
  .command('deploy <target>')
  .description('Deploy to the specified target')
  .action((target) => {
    // commander errors automatically: "error: missing required argument 'target'"
    deploy(target)
  })
```

In click, arguments are required by default:

```python
@cli.command()
@click.argument('target')  # required — click handles: "Error: Missing argument 'TARGET'."
def deploy(target):
    """Deploy to the specified TARGET."""
    pass
```

Never access `argv[n]` or `opts.target` without first confirming the value is defined — opt into your framework's built-in validation rather than writing manual `if (!target)` guards that are easy to miss.

## Detection

- **ID:** `missing-arg-handling`
- **Severity:** `high`
- **What to look for:** List all required arguments across every command. For each, check what happens when required arguments are omitted. In commander, verify `.argument('<required>')` or `.requiredOption()` are used (not just `.argument('optional')`). Check that the framework's built-in validation is active. If custom validation exists, verify it produces helpful messages. Test the pattern: what happens if the user runs `mytool deploy` when `deploy <target>` is expected?
- **Pass criteria:** Omitting a required argument produces a specific error naming the missing argument and showing the correct usage. The framework's built-in required argument validation is active, or equivalent custom validation exists — 100% of missing required arguments must produce a specific error message naming the missing argument. Report: "X required arguments found, all Y produce clear errors when missing."
- **Fail criteria:** Missing required arguments cause an unhandled exception (TypeError, undefined reference), a silent failure (command runs with undefined values), or a generic error that doesn't name the missing argument.
- **Skip (N/A) when:** The CLI has no required arguments — all arguments are optional or have defaults. All checks skip when no CLI entry point is detected.
- **Detail on fail:** `"Running 'mytool deploy' without target argument causes TypeError: Cannot read properties of undefined — the required argument is accessed but not validated"` or `"Missing required argument silently uses 'undefined' as the value — deploy proceeds with undefined target"`
- **Remediation:** Required arguments must be validated before the command handler runs:

  ```ts
  // commander — use angle brackets for required args
  program
    .command('deploy <target>')
    .description('Deploy to the specified target')
    .action((target) => {
      // commander will error automatically if target is missing:
      // "error: missing required argument 'target'"
      deploy(target)
    })
  ```

  ```python
  # click — arguments are required by default
  @cli.command()
  @click.argument('target')  # required by default, click handles the error
  def deploy(target):
      """Deploy to the specified TARGET."""
      pass
  ```

## External references

- cwe CWE-233
- iso-25010 usability.learnability

Taxons: code-quality, user-experience

HTML version: https://auditbuffet.com/patterns/ab-000653
