bash trap not firing on exit or error in CI
A trap handler only runs for the signals it is registered on, and only if it was set before the script exits. A cleanup that never runs in CI usually means the trap targeted the wrong pseudo-signal (ERR vs EXIT), was set too late, or the process was killed by a signal the trap does not catch.
What this error means
Temp files are left behind, or an error-reporting handler never prints, even though the script clearly failed. The trap line exists but the handler did not execute.
# ERR does not fire for a failure inside an if-condition,
# and quoting the wrong way expands $? at trap-set time, not fire time:
trap "echo exit code $?" EXIT # captures $? now (0), not at exitCommon causes
The handler string was expanded too early
Double quotes expand $?, $LINENO, and variables when the trap is set, not when it fires. Use single quotes so expansion is deferred.
Wrong signal, or trap set after the failure
A trap ... ERR does not fire in contexts where errexit is suppressed (if/while conditions, &&/||), and a trap registered after a command cannot catch that command's exit.
How to fix it
Single-quote the handler and set it early
Register the trap at the top of the script and single-quote the command so $? is read when the trap fires.
cleanup() { rm -f "$tmp"; }
trap cleanup EXIT
trap 'echo "failed at line $LINENO (exit $?)"' ERRUse EXIT for guaranteed cleanup
EXIT runs on normal and most abnormal exits, so it is the reliable place for cleanup. Add INT TERM if you must catch interrupts.
trap cleanup EXIT INT TERMHow to prevent it
- Single-quote trap commands so variables expand at fire time.
- Register traps before the code they must protect.
- Prefer
EXITfor cleanup;ERRis skipped in conditions.