set -e vs set -euo pipefail
set -e exits on error but misses pipes, command substitutions, and unset variables. set -euo pipefail is the safer default. Here is what each flag changes.
Tldr
`set -e` exits when a top-level command fails — but ignores failures in pipelines, command substitutions, and inside functions called from conditions. `set -euo pipefail` adds `-u` (error on unset variables) and `-o pipefail` (a pipeline fails if any stage fails). The combined form is the safer default for new Bash scripts.
Sections
Heading
What -e alone catches
Body
`set -e` aborts the script when an "untested" command returns a non-zero exit code. Untested means: not the last command in a pipeline, not on the left of && or ||, not the condition of if/while/until, not inverted with !. So `false` aborts; `false || true` does not. This is a much smaller safety net than most people assume.
Heading
What -u adds
Body
`set -u` (or `set -o nounset`) makes any read of an unset variable an error instead of expanding to empty. It surfaces typos in variable names immediately and prevents the classic `rm -rf "$BASE_DIR/"$SUB` disaster when BASE_DIR is unset. Always use ${VAR:-default} for variables that may legitimately be empty.
Heading
What -o pipefail adds
Body
By default, the exit code of a pipeline is the exit code of the LAST command. So `false | true` succeeds. With pipefail, the pipeline's exit code is the rightmost non-zero exit code. Combined with set -e, this means `cmd1 | cmd2 | cmd3` aborts the script if any stage fails — the behavior most people thought `set -e` provided.
Heading
The recommended preamble
Body
For new Bash scripts: `set -euo pipefail` at the top, optionally with `IFS=
#39;\n\t'` to make word splitting predictable. For POSIX sh, `set -eu` (pipefail is not POSIX).Verdict
Use `set -euo pipefail` for new Bash scripts. It is not a complete safety net — you still need to handle errors explicitly — but it catches three large classes of bugs `set -e` alone misses.
Faq
Q
Does set -e work inside functions?
A
Yes, but only at the top level of the function call — if the function is itself called from an `if` condition or piped, set -e is suspended inside it.
Q
Can I turn -u off temporarily?
A
Yes: `set +u; cmd; set -u`. Better: use `${VAR:-default}` in the specific expansion that may be unset.
Q
Is set -euo pipefail POSIX?
A
No. pipefail is a Bash extension (also in ksh, zsh). For POSIX sh, use `set -eu` and handle pipeline failures manually.