Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

If a Bash ERR trap is defined in your script but stays silent inside a function, command substitution, or subshell, enable -E (also written set -o errtrace). -e and -E do different things: -e controls when Bash may exit after a failing command, while -E makes an existing ERR trap inherited in those contexts. Neither setting makes the trap run for every nonzero status.

What does the missing -E do?

In Bash, set -euo pipefail enables three behaviors: errexit (-e), nounset (-u), and pipefail. It does not enable errtrace. Add -E, or its long form -o errtrace, when you want an installed ERR trap inherited by shell functions, command substitutions, and commands run in a subshell environment.

The GNU Bash Reference Manual, Edition 5.3, updated 18 May 2025, states: “If set, any trap on ERR is inherited by shell functions, command substitutions, and commands executed in a subshell environment.” See the manual’s Shell Builtin Commands section.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do I add it to the script?

Put -E in the shell options before the code that may call a function or create a command substitution or subshell. For example:

#!/usr/bin/env bash
set -Eeuo pipefail

trap 'printf "ERR: status %s at line %sn" "$?" "$LINENO" >&2' ERR

fail() {
  false
}

fail

Here, -E enables inheritance of the parent shell’s trap into fail. The trap is installed before the function call, so the function has a trap to inherit. The example illustrates inheritance; it is not a guarantee that Bash runs an ERR trap for every failure. The command’s syntactic context still matters.

You can use the long option instead: set -euo pipefail -o errtrace. The two forms enable the same errtrace setting.

Why are -e, -E, and pipefail separate?

Setting What it changes What it does not do
-e / errexit Makes Bash exit after certain nonzero statuses, subject to documented exceptions. Does not make an ERR trap inherit into functions, command substitutions, or subshell environments.
-E / errtrace Makes an installed ERR trap inherit into those contexts. Does not make the trap run in contexts where Bash suppresses ERR.
-o pipefail Makes a pipeline return the status of its rightmost failing command, or zero if all commands succeed. Does not enable trap inheritance or change the status of a single command.

These options address different parts of failure handling. -e affects shell exit behavior, -E affects where the trap exists, and pipefail affects the status Bash assigns to a pipeline.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When does Bash still skip an ERR trap?

Even with -E, Bash does not run ERR for every command that returns nonzero. The manual describes exceptions similar to those for errexit. A failing command generally will not trigger the trap when it is:

  • Used as an if or elif test.
  • Used as a while or until condition.
  • Part of an && or || list, except for the command whose status determines the list’s result.
  • A non-final command in a pipeline, subject to the effect of pipefail on the pipeline’s status.
  • Inverted with !.

For example, false in if false; then ...; fi is being used as a condition, so its failure is an expected test result rather than an ordinary unhandled failure. Adding -E does not remove that exception. When debugging a silent trap, check not only whether the failing code runs in a function or subshell, but also how the command is positioned in the surrounding syntax.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Does -E make -e apply inside command substitutions?

No. Trap inheritance and errexit inheritance are distinct. Command substitutions run in subshell environments. Outside POSIX mode, Bash normally clears -e in a command-substitution subshell unless the separate inherit_errexit shell option is enabled. POSIX mode also changes this behavior. The GNU Bash manual explains these rules in Command Execution Environment.

So -E can pass an ERR trap into a command substitution without making -e behave there as it does in the parent shell. If your script depends on both behaviors, configure and test them separately; do not treat errtrace as a substitute for inherit_errexit or POSIX mode.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How should I diagnose a silent trap?

  1. Confirm the shell is Bash. These option names and behaviors are Bash-specific; do not assume another shell handles them the same way.
  2. Check that the trap is installed. A function or subshell can inherit only a trap already set in the relevant parent context.
  3. Enable inheritance. Use set -E or set -o errtrace before the function, command substitution, or subshell command runs.
  4. Inspect the failing command’s context. Determine whether it is an if test, a condition, part of an && or || list, a pipeline component, or negated with !.
  5. For pipelines, check the returned status. pipefail changes how Bash determines pipeline failure; it does not itself propagate the trap.
  6. For command substitutions, check -e separately. If you expect errexit behavior to carry over, review inherit_errexit and POSIX mode in addition to -E.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.