Exit Code 1 vs Exit Code 2: What the Difference Means
Exit 1 means "something failed", full stop. Exit 2 conventionally means "you used me wrong" - bad arguments or syntax - but many tools bend the rule.
Both 1 and 2 are ordinary non-zero failures, but they hint at different root causes. Knowing the loose convention points your debugging in the right direction faster.
Exit code 1: generic failure
By convention, 1 is the catch-all "the operation failed" code. A test that failed, a build error, an assertion, a non-empty grep no-match - almost any tool reaches for 1 when something went wrong but there is no more specific code to use.
Exit code 2: misuse / usage error
Many programs and the shell itself use 2 for "you invoked me incorrectly" - an unknown flag, a missing required argument, or a syntax error. Bash returns 2 for shell syntax errors; tools like grep use 2 specifically for an *error* (bad file, bad regex) as opposed to 1 for "no match".
Why the rule is loose
There is no enforced standard above 0. Plenty of tools (make, pytest, linters) define their own meanings for 1 and 2, so the convention is a hint, not a guarantee. Always confirm against the specific tool’s documented exit codes.
How to act on it in CI
- Exit 1 → read the logs; it is a real failure, not a usage issue.
- Exit 2 → suspect a bad flag, missing arg, or syntax error in the command.
- When unsure, check that tool’s docs - 1 and 2 are tool-defined above the convention.
Key takeaways
- Exit 1 is the generic "it failed" code used by almost everything.
- Exit 2 conventionally means misuse: bad args or syntax errors.
- The convention is loose - many tools redefine 1 and 2 for themselves.
- In CI, exit 2 should make you re-read the command, not just the output.