Skip to content
Latchkey

Bitbucket "after-script" Not Running or Masking Failures

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.sh
after-script:
  - ./upload-coverage.sh   # runs even if tests failed; its exit code is ignored

Common causes

Expecting after-script to affect the step result

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.sh
after-script:
  - if [ "$BITBUCKET_EXIT_CODE" != "0" ]; then ./collect-logs.sh; fi
  - ./teardown.sh || true

Keep real assertions in the main script

  1. Move any check that must fail the build into script, not after-script.
  2. Treat after-script as best-effort cleanup that cannot fail the step.
  3. 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.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →