Bitbucket "after-script" Not Running or Masking Failures
By Kaveh Alemi·Latchkey
after-script runs after the main script whether it passed or failed - useful for cleanup and reporting. Its own exit code does not fail the step, which surprises teams who put real assertions there.
What this error means
Cleanup or reporting placed in after-script does not behave as expected: a failing command there does not fail the build, or commands are missing context because the step already failed. The main result is decided by script, not after-script.
bitbucket-pipelines.yml
script:- ./run-tests.shafter-script:- ./upload-coverage.sh # runs even if tests failed; its exit code is ignored
Diagnose it: schema, branch match, or step isolation?
Bitbucket validates the pipeline file on push, and a schema error disables the pipeline rather than failing a build, which looks like nothing happened. Each step also runs in a fresh container, so nothing carries between steps unless declared.
after-script is for teardown. A non-zero exit there does not turn a passing step red, so assertions placed there never gate the build.
Assuming after-script is skipped on failure
It runs after the main script regardless of pass/fail. Cleanup written assuming success may hit a half-finished state from a failed script.
How to fix it
Use after-script only for cleanup and reporting
Keep teardown idempotent and tolerant of a failed main script. Use BITBUCKET_EXIT_CODE to branch on the result.
bitbucket-pipelines.yml
script:- ./run-tests.shafter-script:- if [ "$BITBUCKET_EXIT_CODE" != "0" ]; then ./collect-logs.sh; fi- ./teardown.sh || true
Keep real assertions in the main script
Move any check that must fail the build into script, not after-script.
Treat after-script as best-effort cleanup that cannot fail the step.
Use BITBUCKET_EXIT_CODE inside after-script to react to the result.
How to prevent it
Put pass/fail logic in script; put cleanup in after-script.
Make after-script tolerant of a failed main script.
Read BITBUCKET_EXIT_CODE to know whether the step passed.
Frequently asked questions
What causes Bitbucket "after-script" not running or masking failures?
There are 2 common causes: expecting after-script to affect the step result and assuming after-script is skipped on failure. after-script is for teardown.
How do I fix Bitbucket "after-script" not running or masking failures?
There are 2 fixes depending on which cause you have: use after-script only for cleanup and reporting and keep real assertions in the main script. Work through them in order, since the first is the most common.
What does Bitbucket "after-script" not running or masking failures actually mean?
Cleanup or reporting placed in after-script does not behave as expected: a failing command there does not fail the build, or commands are missing context because the step already failed.
How do I stop Bitbucket "after-script" not running or masking failures happening again?
Put pass/fail logic in script; put cleanup in after-script. The prevention section lists 3 changes that keep it from recurring.