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.
High because missing required arguments that produce TypeErrors or silent `undefined` behavior give users no actionable path to recovery without reading source code.
Use the framework's native required-argument syntax so validation happens before your handler runs. In commander, angle brackets mark required arguments:
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:
@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.
ID: cli-quality.error-handling.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:
// 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)
})
# 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