Subshell or command substitution exit code
Production Risk
Very common silent bug in bash scripts; always test failure cases.
Subshells (parentheses `()`) and command substitutions (`$()`) have their own exit codes that propagate to the parent. A common bug is capturing command output with `$()` and losing the exit code by assigning it to a variable on the same line.
- 1Assigning `var=$(command)` on one line — the assignment always succeeds (exit 0), losing the command's exit code
- 2set -e not triggering inside `$()`
- 3Expecting a subshell failure to propagate when it is in a condition
Losing a command exit code by assigning in the same statement.
#!/bin/bash set -e # BUG: assignment always exits 0 — set -e won't trigger output=$(false) # false exits 1, but assignment exits 0 echo "Reached here with exit: $?" # prints 0!
expected output
Reached here with exit: 0
Fix
Separate assignment from exit code capture
WHEN Assigning command output AND checking exit code
#!/bin/bash
set -e
# Correct: separate assignment and check
output=$(some_command) || { echo "some_command failed" >&2; exit 1; }
# Or assign then check $? separately:
output=$(some_command)
# With set -e, this line triggers if some_command failedWhy this works
Bash evaluates `var=$(cmd)` as an assignment, which always exits 0. Use `|| {}` to catch the failure inline.
✕ Assume set -e catches failures inside $() assignments
The assignment statement wraps the exit code; set -e does not see the inner failure.
GNU Bash Manual — Command Substitution
BashFAQ — command substitution and exit codes ↗Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev