Execute the following code in bash 3, 4 and 5 respectively, and you will get differing results.

(function handle_error () { echo ERROR; }; trap handle_error ERR; (exit 1))

Imagine that (exit 1) is a command you call which might fail. In this case it always fails, but that doesn't really matter. You would like handle_error to be called when it exits with a non-zero exit code. According to the manual, this is exactly what trap handle_error ERR should do.


I have a local system with a version of bash 3, and a remote system with a completely different operating system with a version of bash 4.

  • bash 3.2.57(1), 3.2.48(1): Returns no output. Excerpt from man bash for the trap builtin:

    If a sigspec is ERR, the command arg is executed whenever a simple command has a non-zero exit status, subject to the following conditions...

  • bash 4.4.23(1), 4.4.12(1): prints ERROR as expected. Excerpt from man bash for the trap builtin:

    If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status, subject to the following conditions...

  • bash 5.0.2(1): prints ERROR as expected.

The documentation leads me to think that the behaviour should be the same over both versions, but it isn't.

I logged onto #bash on Freenode, and verified there as well that this behaviour differs in the same way over all major versions 3, 4 and 5 with their shell bot (nick shbot), which allows you to specify the major version. This shell bot happens to run on a different operating system to both systems which I have tried it on, with differing minor versions over the same major versions of bash which I have access to.


Could anyone point to an authoritative source which explains why this behaviour differs over versions 3, 4 and 5 of bash? I find it hard to believe this this is a bug. There must be another reason which I am missing.

  • Hmm... Testing this in Bash 5.0 shows that it prints ERROR. Setting BASH_COMPAT to e.g. 3.2 does not change this, so it must (?) be related to a fixed bug or similar, in-between release 3 and 4 somewhere. Do you have more exact release numbers than just 3 and 4?
    – Kusalananda
    Feb 19, 2019 at 17:34
  • I've updated the question with the exact versions, and I've tested on version 5 as well now.
    – justinpc
    Feb 19, 2019 at 17:51
  • Obviously exit is a shell built-in; otherwise your script wouldn't stop. So strictly after exit the shell has little chance to do anything, and before it would be just magic.
    – U. Windl
    Apr 28 at 13:16

1 Answer 1


That looks like a bug in Bash 3.2.

I can't find an entry in the changelog that would directly match that. There's only a vague mention about changing the behavior of the errexit option to match POSIX consensus (item l in the change from bash-4.0-rc1 to bash-4.0-release).

That may be related, as there's a similar issue with errexit, this doesn't trigger it in Bash 3.2, but does in Bash 4.0 (it should print nothing, since the shell should exit when the subshell command fails):

$ ./bash3.2 -c 'set -e; (exit 1); echo end.'

Note that the issue here seems to be the subshell, as this works in both versions:

$ ./bash3.2 -c 'trap "echo ERROR" ERR; false'
  • Interesting to see the subshell aspect. I wondered whether the subshell was resetting the traps on return, but (trap "echo ERROR" ERR; (exit 1); trap -p) returns trap -- 'echo ERROR' ERR on bash 3.2.48.
    – justinpc
    Feb 19, 2019 at 18:48
  • What about "b. Fixed a bug that caused subshells to free trap strings associated with inherited signals." in bash-4.4-rc1 to bash-4.4-beta2? The trap still seems to be around though.
    – justinpc
    Feb 19, 2019 at 18:54
  • @justinpc, I tried with 3.2.57(1)-release and 4.0.0(1)-release, so a change in 4.4 is too late
    – ilkkachu
    Feb 19, 2019 at 19:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .