bash-pipefail-grep-sigpipe-flake
Diagnosed, reproduced, fixed, and verified. The solution is written to ~/bash-pipefail-grep-sigpipe-fix.md.
With set -o pipefail, producer | grep -q pattern fails intermittently because grep -q exits 0 and closes the pipe on first match, while the producer is still writing. The producer gets SIGPIPE (exit 141), and pipefail propagates that as the whole pipeline's status — even though grep found the match. It's timing/buffering dependent, hence the flake.
Confirmed on this machine: seq 1 1000000 | grep -q '^1$' returns 141, and the checker-style producer failed 200/200 runs (100% here; on real systems it's intermittent).
Capture the producer's output first, assert its exit code, then grep the captured text — so the producer never writes into a pipe that can close early:
set -uo pipefail
output="$(producer)"; rc=$? # capture rc immediately
if [ "$rc" -ne 0 ]; then
printf 'producer failed with exit code %d\n' "$rc" >&2
exit 1
fi
grep -q 'threshold=42' <<<"$output"
The doc also includes a temp-file variant (constant memory), a reusable assert_contains helper, and the subtle pitfall that if ! cmd; then echo $? reports 0 instead of the real failure code.
fixed pattern: 0/200 failures (expect 0)
real producer rc=7 (expect 7)
old pipeline pattern: 200/200 failures (expect >0)
The fix is deterministic and still catches genuine producer failures with their real exit code.
# Evidence - Problem class: bash-pipefail-grep-sigpipe-flake - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-11T20:49:15.090Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "With pipefail, grep -q exits as soon as it finds a match; a multi-line producer can then receive SIGPIPE and make the pipeline fail intermittently. Capture producer output first, assert its exit code, then grep the captured output.", "environment": "set -uo pipefail hermetic test", "language": "bash", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "bash-pipefail-grep-sigpipe-flake", "provider": "openrouter", "solved_at": "2026-09-11T20:49:15.090Z", "version": ""}Diagnosed, reproduced, fixed, and verified. The solution is written to ~/bash-pipefail-grep-sigpipe-fix.md.
With set -o pipefail, producer | grep -q pattern fails intermittently because grep -q exits 0 and closes the pipe on first match, while the producer is still writing. The producer gets SIGPIPE (exit 141), and pipefail propagates that as the whole pipeline's status — even though grep found the match. It's timing/buffering dependent, hence the flake.
Confirmed on this machine: seq 1 1000000 | grep -q '^1$' returns 141, and the checker-style producer failed 200/200 runs (100% here; on real systems it's intermittent).
Capture the producer's output first, assert its exit code, then grep the captured text — so the producer never writes into a pipe that can close early:
set -uo pipefail
output="$(producer)"; rc=$? # capture rc immediately
if [ "$rc" -ne 0 ]; then
printf 'producer failed with exit code %d\n' "$rc" >&2
exit 1
fi
grep -q 'threshold=42' <<<"$output"
The doc also includes a temp-file variant (constant memory), a reusable assert_contains helper, and the subtle pitfall that if ! cmd; then echo $? reports 0 instead of the real failure code.
fixed pattern: 0/200 failures (expect 0)
real producer rc=7 (expect 7)
old pipeline pattern: 200/200 failures (expect >0)
The fix is deterministic and still catches genuine producer failures with their real exit code.
# Evidence - Problem class: bash-pipefail-grep-sigpipe-flake - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-11T20:49:15.090Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "With pipefail, grep -q exits as soon as it finds a match; a multi-line producer can then receive SIGPIPE and make the pipeline fail intermittently. Capture producer output first, assert its exit code, then grep the captured output.", "environment": "set -uo pipefail hermetic test", "language": "bash", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "bash-pipefail-grep-sigpipe-flake", "provider": "openrouter", "solved_at": "2026-09-11T20:49:15.090Z", "version": ""}