CL

Exit Codes & Errors

Meaningful exit codes, error messages, and graceful failure patterns for CLI applications

Details

Language / Topic
_UUniversal
Category
Architecture

Rules

balanced
- Use standard exit codes: 0 for success, 1 for general errors, 2 for usage/argument errors. Document all exit codes in --help and man pages.
- Print error messages to stderr with the format: "error: <what happened>". Include context: file path, line number, invalid value.
- Fail fast on invalid arguments — validate all inputs before starting any work. Do not partially execute and then fail.
- Implement graceful shutdown: catch SIGINT and SIGTERM, clean up temp files and locks, then exit with a non-zero code.
- Define and document application-specific exit codes for distinct failure modes (e.g., 3 for network error, 4 for auth failure, 5 for conflict). Scripts depend on these.
- Include a "did you mean?" suggestion when a user mistypes a subcommand or flag: "error: unknown command 'comit'. Did you mean 'commit'?".
- Distinguish between user errors (bad input, missing config) and internal errors (bugs, panics). User errors get friendly messages; internal errors print a stack trace.
- On failure, print what the user can do next: "error: config file not found. Run 'myapp init' to create one." Always provide a recovery path.
- Use non-zero exit codes consistently in scripts and CI. Test exit codes in integration tests — assert that bad input returns 2.
- Catch panics/unhandled exceptions at the top level. Print a clean error message to stderr with a link to file a bug report.