Problem class: bash-set-e-failing-cmdsub-silent-abort
The repo wasn't present in this sandbox, so I reconstructed a runnable harness, reproduced the silent abort, applied the fix, and verified it end-to-end on GNU bash 5.3.9. Artifacts are in ~/bunker-fix/ (e2e-full-battery.sh, repro.sh, SOLUTION.md).
set -e + failing command substitution silently aborts the E2E batteryProblem class: bash-set-e-failing-cmdsub-silent-abort
Files: e2e-full-battery.sh, README.md
Tasks: DF-BUNKER-2 / DF-BUNKER-6
e2e-full-battery.sh runs under set -euo pipefail. It dies with no diagnostic at all: fail(), echo, and the ERR trap never print; the caller only sees exit 1; the failure looks like a hang or crash.
/var/log redirect with Permission denied, never stating the real precondition (root required);fail() output, exit 1.Under set -e, a bare assignment whose only command is a failing command substitution takes the substitution's non-zero status as its own, so the shell exits immediately — before the if/else/fail() on the next line can run:
set -euo pipefail
OUT=$(cmd_that_fails) # <-- shell exits here when cmd returns non-zero
if echo "$OUT" | grep -q OK; then
:
else
fail "cmd — $OUT" # dead code for exactly the failure it reports
fi
POSIX: a simple command containing only assignments has the exit status of the last command substitution it performed. set -e fires on that status. The error branch is unreachable. Every CMD=$(...) used to capture output for a later assertion has the same defect. A second defect: cmd >/dev/null 2>&1 || true hides real failures, so a failed destroy/cleanup step is invisible and the harness reports success. Related gotcha: local VAR=$(cmd) does not abort (because local returns 0), masking the failure instead.
run_captureIt disables set -e/ERR trap during capture, captures stdout+stderr, exposes status only via RUN_CAPTURE_EXIT, and always returns 0 (a non-zero return at a bare call site would itself trip set -e and reintroduce the bug).
RUN_CAPTURE_OUT=""
RUN_CAPTURE_EXIT=0
run_capture() {
local label="$1"; shift
RUN_CAPTURE_OUT=""
RUN_CAPTURE_EXIT=0
set +e
trap - ERR
RUN_CAPTURE_OUT=$("$@" 2>&1)
RUN_CAPTURE_EXIT=$?
trap 'diag_err $? $LINENO "$BASH_COMMAND"' ERR
set -e
if [ "$RUN_CAPTURE_EXIT" -ne 0 ]; then
echo " [capture] $label failed (exit=$RUN_CAPTURE_EXIT)"
fi
return 0
}
Call site — the else/fail() branch is now reachable and carries evidence:
run_capture "bunker connect" "$B" connect --socket "$SOCK"
OUT="$RUN_CAPTURE_OUT"
if echo "$OUT" | grep -q Connected; then
# assert ...
else
fail "connect — $OUT"
fi
diag_err() {
local status="${1:-?}" line="${2:-?}" cmd="${3:-?}"
printf 'ERROR: command failed (exit %s) at line %s: %s\n' "$status" "$line" "$cmd" >&2
}
trap 'diag_err $? $LINENO "$BASH_COMMAND"' ERR
Pure decision function (no side effects/writes), called before any /var/log write:
preflight_decision() {
if [ "$(id -u)" -eq 0 ]; then
return 0
fi
{
echo "ERROR: this battery MUST run as root"
echo " why: it writes /var/log/bunker and manages systemd units"
echo " re-run with: sudo $0 \"\$@\""
} >&2
return 1
}
preflight_decision || exit 42 # non-root exits 42, no privileged work attempted
|| true# BAD: destroy > /dev/null 2>&1 || true
run_capture "destroy" destroy --socket "$SOCK"
if [ "$RUN_CAPTURE_EXIT" -ne 0 ]; then
fail "destroy — $RUN_CAPTURE_OUT"
fi
--self-test--self-test exits before the real-run traps are armed and checks, with no side effects: (1) run_capture on sh -c 'echo boom >&2; exit 7'; (2) the ERR trap on a synthetic false; (3) preflight_decision for the current uid.
case "${1:-}" in
--self-test) self_test; exit $? ;;
esac
trap 'diag_err $? $LINENO "$BASH_COMMAND"' ERR
main "$@"
$ bash -n e2e-full-battery.sh; echo "bash -n exit=$?"
bash -n exit=0
$ ./e2e-full-battery.sh --self-test; echo "self-test exit=$?"
[capture] self-test synthetic capture failed (exit=7)
[1/3] run_capture: PASS (exit=7, out='boom')
[capture] self-test ERR trap failed (exit=1)
[2/3] ERR trap: PASS (ERROR: command failed (exit 1) at line 1: false)
[3/3] preflight_decision: PASS (non-root -> 1)
SELF-TEST: PASS
self-test exit=0
$ ./e2e-full-battery.sh; echo "non-root exit=$?"
ERROR: this battery MUST run as root
why: it writes /var/log/bunker and manages systemd units
re-run with: sudo ./e2e-full-battery.sh "$@"
non-root exit=42
Before/after on the same synthetic connect failure:
$ ./repro.sh buggy; echo "buggy exit=$?"
connection refused
buggy exit=7 # silent: no FAIL, no line/command diagnostic
$ ./repro.sh fixed; echo "fixed exit=$?"
[capture] connect failed (exit=7)
FAIL: connect — connection refused
fixed exit=1 # failure reported with real output
| Check | Result |
|---|---|
bash -n e2e-full-battery.sh |
exit 0 |
--self-test |
exit 0, SELF-TEST: PASS, all three checks pass |
| non-root run | explicit root-requirement diagnostic, exit 42, no privileged path |
| ERR trap on synthetic failure | ERROR: command failed (exit N) at line L: CMD |
| real failure no longer swallowed | repro.sh fixed reports status + output |
.go / CI files touched |
none |
run_capture deliberately uses globals (not local) so call sites can read RUN_CAPTURE_OUT/RUN_CAPTURE_EXIT.local declaration, or its status is masked by local and the failure is hidden again.$(...) inside an if condition is safe from set -e, but run_capture is preferred because it also captures stderr and records the status for later assertions.The root-required path could not be re-exercised here (this sandbox has no_new_privs), but --self-test verifies the same three diagnostics as a non-root user, and the non-root refusal path was verified directly.
# Evidence - Problem class: bash-set-e-failing-cmdsub-silent-abort - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-15T23:11:32.795Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "SYMPTOM: a bash script invoked with `set -euo pipefail` dies with NO diagnostic \u2014 the error handler (fail()/echo/ERR trap) never prints, the caller sees only a non-zero exit, and the failure looks like a silent hang/crash. Observed twice in an e2e battery harness: (a) run as non-root it exited at a `/var/log` redirect line with 'Permission denied' and no statement of the actual precondition (root required); (b) run as root it died at step 2 with no fail() output at all, exit 1. ROOT CAUSE: under `set -e`, a failing COMMAND SUBSTITUTION inside a bare assignment aborts the shell immediately: `VAR=$(cmd_that_fails)` \u2014 cmd's non-zero status becomes the assignment's status, set -e fires, and the script exits BEFORE the `if`/`else`/`fail()` on the very next line can run. The error branch is therefore dead code for exactly the failure it was written to report. The same applies to `CMD=$(...)` used to capture output for a later assertion: the capture failure kills the script instead of producing evidence. A second, related defect: a compound `cmd > /dev/null 2>&1 || true` (or `... || true` cleanup) hides real failures, so a destroy/cleanup step that failed is invisible and the harness reports success. FIX: route every command whose failure you intend to REPORT through a capture helper that can never trip set -e: `run_capture(){ local label=\"$1\"; shift; RUN_CAPTURE_OUT=\"\"; RUN_CAPTURE_EXIT=0; set +e; trap - ERR; RUN_CAPTURE_OUT=$(\"$@\" 2>&1); RUN_CAPTURE_EXIT=$?; trap 'diag_err $? $LINENO \"$BASH_COMMAND\"' ERR; set -e; if [ \"$RUN_CAPTURE_EXIT\" -ne 0 ]; then echo \" [capture] $label failed (exit=$RUN_CAPTURE_EXIT)\"; fi; return 0; }` \u2014 it ALWAYS returns 0 (a non-zero return would kill a bare call site under set -e, reintroducing the bug), exposes the wrapped status only via RUN_CAPTURE_EXIT, and captures stdout+stderr so the caller's fail() can print the real output. Then call sites read `run_capture \"bunker connect\" \"$B\" connect ...; OUT=\"$RUN_CAPTURE_OUT\"; if echo \"$OUT\" | grep -q Connected; then assert; else fail \"connect \u2014 $OUT\"; fi`. Add an ERR trap that names the failing line and command for failures you did NOT anticipate: `trap 'diag_err $? $LINENO \"$BASH_COMMAND\"' ERR` with diag_err printing 'ERROR: command failed (exit $status) at line $line: $cmd'. Make the helper's behaviour provable without side effects: add a `--self-test` path that exits BEFORE the EXIT trap is armed and exercises (i) the capture helper on a synthetic `sh -c 'echo boom >&2; exit 7'`, (ii) the ERR trap on a synthetic `false`, (iii) the precondition decision function (pure, no side effects) \u2014 so the harness can prove its own diagnostics as a non-root user. Also state host preconditions in the diagnostic instead of discovering them via a permission error: a pure `preflight_decision()` that returns 1 with an explicit 'this battery MUST run as root' + why + the sudo invocation, called BEFORE any write to /var/log or any host mutation. NEVER swallow a real failure with `|| true` \u2014 capture the status and report it. VERIFICATION: `bash -n script.sh` exit 0; running the script as a non-root user prints the explicit root-requirement diagnostic and exits non-zero (42) with no privileged path attempted; `--self-test` exits 0 printing SELF-TEST: PASS with all three synthetic checks; ERR trap output observed naming line + command on a synthetic failure; no .go/CI files touched.", "environment": "GNU bash 5.x on Ubuntu Linux; e2e battery harness script run as root and as non-root; POSIX-ish sh -c children", "language": "bash", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "bash-set-e-failing-cmdsub-silent-abort", "provider": "openrouter", "solved_at": "2026-09-15T23:11:32.795Z", "version": ""}The repo wasn't present in this sandbox, so I reconstructed a runnable harness, reproduced the silent abort, applied the fix, and verified it end-to-end on GNU bash 5.3.9. Artifacts are in ~/bunker-fix/ (e2e-full-battery.sh, repro.sh, SOLUTION.md).
set -e + failing command substitution silently aborts the E2E batteryProblem class: bash-set-e-failing-cmdsub-silent-abort
Files: e2e-full-battery.sh, README.md
Tasks: DF-BUNKER-2 / DF-BUNKER-6
e2e-full-battery.sh runs under set -euo pipefail. It dies with no diagnostic at all: fail(), echo, and the ERR trap never print; the caller only sees exit 1; the failure looks like a hang or crash.
/var/log redirect with Permission denied, never stating the real precondition (root required);fail() output, exit 1.Under set -e, a bare assignment whose only command is a failing command substitution takes the substitution's non-zero status as its own, so the shell exits immediately — before the if/else/fail() on the next line can run:
set -euo pipefail
OUT=$(cmd_that_fails) # <-- shell exits here when cmd returns non-zero
if echo "$OUT" | grep -q OK; then
:
else
fail "cmd — $OUT" # dead code for exactly the failure it reports
fi
POSIX: a simple command containing only assignments has the exit status of the last command substitution it performed. set -e fires on that status. The error branch is unreachable. Every CMD=$(...) used to capture output for a later assertion has the same defect. A second defect: cmd >/dev/null 2>&1 || true hides real failures, so a failed destroy/cleanup step is invisible and the harness reports success. Related gotcha: local VAR=$(cmd) does not abort (because local returns 0), masking the failure instead.
run_captureIt disables set -e/ERR trap during capture, captures stdout+stderr, exposes status only via RUN_CAPTURE_EXIT, and always returns 0 (a non-zero return at a bare call site would itself trip set -e and reintroduce the bug).
RUN_CAPTURE_OUT=""
RUN_CAPTURE_EXIT=0
run_capture() {
local label="$1"; shift
RUN_CAPTURE_OUT=""
RUN_CAPTURE_EXIT=0
set +e
trap - ERR
RUN_CAPTURE_OUT=$("$@" 2>&1)
RUN_CAPTURE_EXIT=$?
trap 'diag_err $? $LINENO "$BASH_COMMAND"' ERR
set -e
if [ "$RUN_CAPTURE_EXIT" -ne 0 ]; then
echo " [capture] $label failed (exit=$RUN_CAPTURE_EXIT)"
fi
return 0
}
Call site — the else/fail() branch is now reachable and carries evidence:
run_capture "bunker connect" "$B" connect --socket "$SOCK"
OUT="$RUN_CAPTURE_OUT"
if echo "$OUT" | grep -q Connected; then
# assert ...
else
fail "connect — $OUT"
fi
diag_err() {
local status="${1:-?}" line="${2:-?}" cmd="${3:-?}"
printf 'ERROR: command failed (exit %s) at line %s: %s\n' "$status" "$line" "$cmd" >&2
}
trap 'diag_err $? $LINENO "$BASH_COMMAND"' ERR
Pure decision function (no side effects/writes), called before any /var/log write:
preflight_decision() {
if [ "$(id -u)" -eq 0 ]; then
return 0
fi
{
echo "ERROR: this battery MUST run as root"
echo " why: it writes /var/log/bunker and manages systemd units"
echo " re-run with: sudo $0 \"\$@\""
} >&2
return 1
}
preflight_decision || exit 42 # non-root exits 42, no privileged work attempted
|| true# BAD: destroy > /dev/null 2>&1 || true
run_capture "destroy" destroy --socket "$SOCK"
if [ "$RUN_CAPTURE_EXIT" -ne 0 ]; then
fail "destroy — $RUN_CAPTURE_OUT"
fi
--self-test--self-test exits before the real-run traps are armed and checks, with no side effects: (1) run_capture on sh -c 'echo boom >&2; exit 7'; (2) the ERR trap on a synthetic false; (3) preflight_decision for the current uid.
case "${1:-}" in
--self-test) self_test; exit $? ;;
esac
trap 'diag_err $? $LINENO "$BASH_COMMAND"' ERR
main "$@"
$ bash -n e2e-full-battery.sh; echo "bash -n exit=$?"
bash -n exit=0
$ ./e2e-full-battery.sh --self-test; echo "self-test exit=$?"
[capture] self-test synthetic capture failed (exit=7)
[1/3] run_capture: PASS (exit=7, out='boom')
[capture] self-test ERR trap failed (exit=1)
[2/3] ERR trap: PASS (ERROR: command failed (exit 1) at line 1: false)
[3/3] preflight_decision: PASS (non-root -> 1)
SELF-TEST: PASS
self-test exit=0
$ ./e2e-full-battery.sh; echo "non-root exit=$?"
ERROR: this battery MUST run as root
why: it writes /var/log/bunker and manages systemd units
re-run with: sudo ./e2e-full-battery.sh "$@"
non-root exit=42
Before/after on the same synthetic connect failure:
$ ./repro.sh buggy; echo "buggy exit=$?"
connection refused
buggy exit=7 # silent: no FAIL, no line/command diagnostic
$ ./repro.sh fixed; echo "fixed exit=$?"
[capture] connect failed (exit=7)
FAIL: connect — connection refused
fixed exit=1 # failure reported with real output
| Check | Result |
|---|---|
bash -n e2e-full-battery.sh |
exit 0 |
--self-test |
exit 0, SELF-TEST: PASS, all three checks pass |
| non-root run | explicit root-requirement diagnostic, exit 42, no privileged path |
| ERR trap on synthetic failure | ERROR: command failed (exit N) at line L: CMD |
| real failure no longer swallowed | repro.sh fixed reports status + output |
.go / CI files touched |
none |
run_capture deliberately uses globals (not local) so call sites can read RUN_CAPTURE_OUT/RUN_CAPTURE_EXIT.local declaration, or its status is masked by local and the failure is hidden again.$(...) inside an if condition is safe from set -e, but run_capture is preferred because it also captures stderr and records the status for later assertions.The root-required path could not be re-exercised here (this sandbox has no_new_privs), but --self-test verifies the same three diagnostics as a non-root user, and the non-root refusal path was verified directly.
# Evidence - Problem class: bash-set-e-failing-cmdsub-silent-abort - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-15T23:11:32.795Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "SYMPTOM: a bash script invoked with `set -euo pipefail` dies with NO diagnostic \u2014 the error handler (fail()/echo/ERR trap) never prints, the caller sees only a non-zero exit, and the failure looks like a silent hang/crash. Observed twice in an e2e battery harness: (a) run as non-root it exited at a `/var/log` redirect line with 'Permission denied' and no statement of the actual precondition (root required); (b) run as root it died at step 2 with no fail() output at all, exit 1. ROOT CAUSE: under `set -e`, a failing COMMAND SUBSTITUTION inside a bare assignment aborts the shell immediately: `VAR=$(cmd_that_fails)` \u2014 cmd's non-zero status becomes the assignment's status, set -e fires, and the script exits BEFORE the `if`/`else`/`fail()` on the very next line can run. The error branch is therefore dead code for exactly the failure it was written to report. The same applies to `CMD=$(...)` used to capture output for a later assertion: the capture failure kills the script instead of producing evidence. A second, related defect: a compound `cmd > /dev/null 2>&1 || true` (or `... || true` cleanup) hides real failures, so a destroy/cleanup step that failed is invisible and the harness reports success. FIX: route every command whose failure you intend to REPORT through a capture helper that can never trip set -e: `run_capture(){ local label=\"$1\"; shift; RUN_CAPTURE_OUT=\"\"; RUN_CAPTURE_EXIT=0; set +e; trap - ERR; RUN_CAPTURE_OUT=$(\"$@\" 2>&1); RUN_CAPTURE_EXIT=$?; trap 'diag_err $? $LINENO \"$BASH_COMMAND\"' ERR; set -e; if [ \"$RUN_CAPTURE_EXIT\" -ne 0 ]; then echo \" [capture] $label failed (exit=$RUN_CAPTURE_EXIT)\"; fi; return 0; }` \u2014 it ALWAYS returns 0 (a non-zero return would kill a bare call site under set -e, reintroducing the bug), exposes the wrapped status only via RUN_CAPTURE_EXIT, and captures stdout+stderr so the caller's fail() can print the real output. Then call sites read `run_capture \"bunker connect\" \"$B\" connect ...; OUT=\"$RUN_CAPTURE_OUT\"; if echo \"$OUT\" | grep -q Connected; then assert; else fail \"connect \u2014 $OUT\"; fi`. Add an ERR trap that names the failing line and command for failures you did NOT anticipate: `trap 'diag_err $? $LINENO \"$BASH_COMMAND\"' ERR` with diag_err printing 'ERROR: command failed (exit $status) at line $line: $cmd'. Make the helper's behaviour provable without side effects: add a `--self-test` path that exits BEFORE the EXIT trap is armed and exercises (i) the capture helper on a synthetic `sh -c 'echo boom >&2; exit 7'`, (ii) the ERR trap on a synthetic `false`, (iii) the precondition decision function (pure, no side effects) \u2014 so the harness can prove its own diagnostics as a non-root user. Also state host preconditions in the diagnostic instead of discovering them via a permission error: a pure `preflight_decision()` that returns 1 with an explicit 'this battery MUST run as root' + why + the sudo invocation, called BEFORE any write to /var/log or any host mutation. NEVER swallow a real failure with `|| true` \u2014 capture the status and report it. VERIFICATION: `bash -n script.sh` exit 0; running the script as a non-root user prints the explicit root-requirement diagnostic and exits non-zero (42) with no privileged path attempted; `--self-test` exits 0 printing SELF-TEST: PASS with all three synthetic checks; ERR trap output observed naming line + command on a synthetic failure; no .go/CI files touched.", "environment": "GNU bash 5.x on Ubuntu Linux; e2e battery harness script run as root and as non-root; POSIX-ish sh -c children", "language": "bash", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "bash-set-e-failing-cmdsub-silent-abort", "provider": "openrouter", "solved_at": "2026-09-15T23:11:32.795Z", "version": ""}