/flags/github-actions/shell-bash-pipefail
GitHub Actions shell: bash vs the default: -e and pipefail
verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · 1.7.12updated 2026-10-20
- tool
- GitHub Actions
- command
- jobs.<job>.steps[*].shell / defaults.run.shell
- flag
- shell: bash
- default
- bash -e {0} (Linux and macOS)
On Linux and macOS runners a run: step without shell: is executed as bash -e {0}: the step stops at the first failing command, but not when the failure is inside a pipeline whose last command succeeds. Writing shell: bash changes the command to bash --noprofile --norc -eo pipefail {0}, so a failure anywhere in a pipeline fails the step.
The difference, reproduced
The same step script under both invocations ({0} is the script file the runner writes):
cat > step.sh <<'EOF'
grep error missing.log | sort
echo "still running after the failed grep"
EOF
echo "--- default: bash -e {0}"
bash -e step.sh; echo "step exit status: $?"
echo "--- shell: bash: bash --noprofile --norc -eo pipefail {0}"
bash --noprofile --norc -eo pipefail step.sh; echo "step exit status: $?"Output
--- default: bash -e {0}
grep: missing.log: No such file or directory
still running after the failed grep
step exit status: 0
--- shell: bash: bash --noprofile --norc -eo pipefail {0}
grep: missing.log: No such file or directory
step exit status: 2With the default, grep fails but sort succeeds, the pipeline counts as successful, and the step goes on and passes. With shell: bash, the step fails right there.
Set it once for the whole workflow
defaults:
run:
shell: bash
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: curl -fsSL https://example.com/data.json | jq '.items | length'Shells and their commands
| shell: | Runs |
|---|---|
| (unspecified, Linux/macOS) | bash -e {0} |
| bash | bash --noprofile --norc -eo pipefail {0} |
| sh | sh -e {0} |
| pwsh | pwsh -command ". '{0}'" (default on Windows runners) |
| python | python {0} |
| custom | any command containing {0}, e.g. bash -euxo pipefail {0} |
Sources
Related pages
flags · bashset -euo pipefail: what each flag does in bashset -e exits on the first failing command, -u treats unset variables as errors and -o pipefail makes a pipeline fail if any command in it fails. Examples.errors · github-actionsGitHub Actions: Error: Process completed with exit code 1Process completed with exit code 1 means the last command of a run step failed. Scroll up to the first error in the log; bash -e stops at that command.cheat sheets · github-actionsGitHub Actions cheat sheet: triggers, jobs, matrix, outputs and cachingGitHub Actions cheat sheet: triggers, jobs and needs, matrix builds, if conditions, step and job outputs, secrets and env, caching, artifacts, contexts.