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.