Exit code 2: argument or usage error (the invocation itself is wrong)
Exit code 2 means the command was called with invalid arguments or a usage error — the shell or the program could not parse what it was given. It is a reserved convention in Bash (misuse of a shell builtin) and widely followed by utilities like `curl`, `grep`, `tar`, and most CLI tools. Unlike exit 1 (a runtime failure), a 2 usually means the invocation itself is wrong: a bad flag, a missing required argument, or a changed CLI between versions.
Why exit 2 rather than exit 1?
The convention comes from the POSIX shell spec and the GNU Bash manual: exit 1 means a generic runtime failure (the program ran but something went wrong during execution), while exit 2 means the invocation itself was malformed — a bad flag, an unrecognised option, or a missing required argument. The program never did any real work; it stopped immediately after failing to parse its own arguments.
Many widely-used CLI tools follow this convention: `curl` exits 2 on bad arguments, `grep` exits 2 on a usage error, and most tools built on argument-parsing libraries (argparse, cobra, clap) do the same. A version upgrade that renames a flag can silently turn a working invocation into an exit 2.
How do I reproduce and diagnose an exit 2?
Run the command manually in a shell with the exact arguments cron uses, adding -v or --verbose where the tool supports it. The tool will print its usage output or an error line naming the unrecognised flag before exiting. That line is the diagnosis:
# Run exactly as cron would, capturing both stdout and stderr:
/usr/local/bin/aws s3 sync --badflags s3://bucket . 2>&1
# aws: error: argument --badflags: ignored explicit argument ''
# exit 2How do I fix an exit 2 in a cron job?
- Read the usage output: run the command with --help and compare the flags you're passing against what's accepted. A renamed or removed flag from a version upgrade is the most common culprit.
- Check the tool version in cron's environment: cron may run a different binary than your interactive shell (different PATH or a virtualenv). Use the absolute path to confirm you're testing the same binary.
- Check for required arguments: if the tool requires a positional argument and it's missing (e.g., a file path that was correct in dev but wrong on the cron server), the tool exits 2 immediately.
- Pin CLI versions: if a dependency upgrade changed a flag's syntax, pin the version in your dependency manager or update the invocation to match the new API.
How do I get alerted when a cron job exits 2?
Because exit 2 means the job never did any real work, you want the monitor to fire immediately. Ping only on success so any non-zero exit withholds the ping:
#!/usr/bin/env bash
set -euo pipefail
/usr/local/bin/your-tool --correct-flag value
# Only reached if the tool exited 0.
curl -fsS -m 10 --retry 3 "https://ping.cronshield.com/<your-check-id>"Catch this failure automatically
The free tier gives you a heartbeat endpoint and an email alert when an expected ping doesn't arrive. Paid tiers add the log-aware diagnosis — the last log line and a likely cause in the alert. The heartbeat receiver ships in an upcoming release; see the plans to learn what each tier adds.
Frequently asked questions
- Is exit 2 a runtime error or a configuration error?
- It is a configuration error in the invocation — the program did not run any of its intended work. The argument or flag you passed was not recognised, and the program printed its usage output and exited. No data was processed, no side effects happened.
- Can a dependency version upgrade cause exit 2?
- Yes. A CLI tool that renames a flag or removes an option in a new version will exit 2 on the old invocation. Always test cron jobs after upgrading tools, and read the changelog for breaking changes to the CLI interface.
Primary sources
- GNU Bash Manual — Exit Status (exit 2 = misuse of shell builtin; reserved by the shell) — verified 2026-07-05
- curl(1) man page — exit code 2: failed to initialise / argument error — verified 2026-07-05