Skip to content
Latchkey

Shell pipefail not set masks a pipeline failure in CI

By default a shell pipeline reports only the exit status of its last command. So failing-cmd | tee log returns tee's success and the step goes green. set -o pipefail makes the pipeline return the rightmost non-zero status instead.

What this error means

A build or test that clearly errored still passes CI. The command that failed was piped into tee, grep, head, or sort, whose success became the pipeline's exit code.

bash
# without pipefail, this step exits 0 even though the build failed:
make build 2>&1 | tee build.log
# $? is tee's status, not make's

Common causes

A failing command piped into a succeeding one

The default status is the last command's. Piping a build or test into tee/grep swallows the real failure because the trailing filter exits 0.

pipefail is not the default in most shells

Neither bash nor sh enables pipefail automatically, so CI steps that use pipes silently mask upstream failures unless it is set explicitly.

How to fix it

Enable pipefail

Set it at the top of the script (bash) so any failing stage fails the pipeline.

bash
set -o pipefail
make build 2>&1 | tee build.log

Set the CI shell to include pipefail

GitHub Actions bash steps run with pipefail by default, but a custom shell or explicit shell: sh may not. Set it explicitly to be safe.

.github/workflows/ci.yml
defaults:
  run:
    shell: bash   # runs with -eo pipefail

How to prevent it

  • Add set -o pipefail to every non-trivial script.
  • Keep the exit-critical command as the last stage where practical.
  • Confirm your CI shell enables pipefail, especially with custom shells.

Frequently asked questions

What causes "missing pipefail hides a failure"?
The default status is the last command's. Piping a build or test into tee/grep swallows the real failure because the trailing filter exits 0.
How do I fix missing pipefail hides a failure?
Set it at the top of the script (bash) so any failing stage fails the pipeline.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card