Terminal · intermediate
Shell error handling
Shell error handling combines explicit status checks, intentional propagation, validated inputs, cleanup, and selectively enabled shell options rather than relying on exceptions.
Why it matters
Shell commands fail through statuses in many syntactic contexts, and blunt strict-mode folklore can either miss failures or stop on expected negative results.
Mental model
How to reason about shell error handling
Classify each command outcome, handle expected alternatives locally, propagate unexpected nonzero status at a deliberate boundary, and register cleanup for resources already created.
Analogy
It is a checklist with known alternate outcomes and evacuation steps, not a single alarm switch assumed to understand every operation in the building.
Examples
See the boundary, not just the happy path
Worked example · Handle an expected negative result
if grep -qF needle file; then found=yes; elif [ "$?" -eq 1 ]; then found=no; else exit 1; fiThe branches distinguish grep's match, no-match, and error outcomes instead of treating every nonzero result identically.
Worked example · Validate required input early
: "${OUTPUT_DIR:?OUTPUT_DIR must be set}"Parameter expansion stops a non-interactive shell with a targeted diagnostic before a missing variable can resolve to an unsafe path.
Avoid · Strict mode as a complete strategy
set -euo pipefailThese Bash options can be useful under a documented shell, but context-sensitive errexit behavior and expected nonzero statuses still require explicit design.
Common mistakes
Misconceptions to remove early
Assuming set -e fires after every nonzero status
errexit has specified exceptions in conditionals, lists, and pipelines, and its behavior interacts with functions and shell versions.
Suppressing every error with || true
This erases the distinction between an expected condition and an operational failure; test or document the exact accepted statuses instead.
Quick check
Can you predict the result?
1. Why is set -e not a substitute for explicit error handling?
2. What should a script do with a command that uses distinct nonzero statuses for no result and operational error?
Keep building