Not sure if this is a documentation bug or a functional one, but the man page does not seem to agree with the observed behavior for return when invoked in DEBUG traps.
return [n] Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body. ... If return is executed by a trap handler, the last command used to determine the status is the last command executed before the trap handler. ... If return is executed during a DEBUG trap, the last command used to determine the status is the last command executed by the trap handler before return was invoked. It seems that when return is used in a DEBUG trap, any explicit return value used is ignored. For example: fun1() { trap "trap - DEBUG; (exit 1); return" DEBUG; :; } fun1; echo $? # 1, as expected fun2() { trap "trap - DEBUG; (exit 1); return 2" DEBUG; :; } fun2; echo $? # also 1! The man page doesn't mention anything about the RETURN trap, but it seems to function the same way as the DEBUG trap does in this regard. fun3() { trap 'trap - RETURN; (exit 1); return 2' RETURN; (exit 3); return 4; } fun3; echo $? # also 1! There's also a minor inconsistency between the help topic and the man page regarding which traps are inherited when functrace is on: -T If set, any traps on DEBUG and RETURN are inherited by shell functions, command substitutions, and commands executed in a subshell environment. The DEBUG and RETURN traps are normally not inherited in such cases. -T If set, the DEBUG trap is inherited by shell functions.