BASH_VERSION: 5.1.4(1)-release (shipped with Debian 11) Considering script like this:
1 #!/usr/bin/env bash 2 3 set -o errexit 4 set -o errtrace 5 6 bt() { 7 local line file file_v 8 9 for ((idx = 1; idx < ${#FUNCNAME[@]}; idx++)); do 10 read -r line _ file < <(caller $((idx - 1))) 11 file_v=${file//[\/\.]/_} 12 13 [[ -f $file ]] || continue 14 15 if [[ ! -v $file_v ]]; then 16 mapfile -t "${file_v}_ref" <"$file" 17 fi 18 local -n file_ref=${file_v}_ref 19 20 echo "$file -> $line: ${file_ref[line - 1]}" 21 done 22 23 } 24 25 a() { 26 false \ 27 foo \ 28 bar 29 } 30 31 trap 'bt' ERR 32 33 a With a()'s `false` triggering the ERR trap I would expect output from bt() to point at line 26, however, the BASH_LINENO holds, surprisingly to me, line 27: $ bash ./t ./t -> 27: foo \ ./t -> 33: a If I don't break the failing line then the BASH_LINENO is set just fine: $ bash ./t ./t -> 26: false foo bar ./t -> 31: a Same thing happens if the ERR is triggered outside the function. So like this: 1 #!/usr/bin/env bash 2 3 set -o errexit 4 set -o errtrace 5 6 bt() { 7 local line sub file file_v 8 9 for ((idx = 1; idx < ${#FUNCNAME[@]}; idx++)); do 10 read -r line sub file < <(caller $((idx - 1))) 11 file_v=${file//[\/\.]/_} 12 13 [[ -f $file ]] || continue 14 15 if [[ ! -v ${file_v}_ref ]]; then 16 mapfile -t "${file_v}_ref" <"$file" 17 fi 18 local -n file_ref=${file_v}_ref 19 20 echo "$file -> $line: ${file_ref[line - 1]}" 21 done 22 23 } 24 25 trap 'bt' ERR 26 27 false \ 28 foo \ 29 bar 30 gives this: $ bash ./t ./t -> 28: foo \ Not sure if this is expected so any hints would be appreciated. :) Regards, Michal