Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How many entries are included in Erlang stack traces?

When looking at stack traces from errors in an Erlang program, it sometimes seems to me that I'm not seeing the whole picture, that some of the entries have been removed. Is there a limit to how many entries are included in the stack trace?

like image 959
legoscia Avatar asked Dec 01 '25 00:12

legoscia


1 Answers

First of all, if the stack trace is being printed as an Erlang term, note that io:format might truncate the list if it is deep enough. If that happens, you'll see ... in the output.

Secondly, if it seems like entries are missing from the middle of the stack trace, it's probably because of tail call optimisation. If the last thing a function does is calling another function, then the calling function's stack frame is eliminated and will not be visible in the stack trace.

Apart from that, only the last (innermost) eight stack frames are included in the stack trace. For example, given a program that signals an error twelve frames deep (see listing below), you get this output:

1> foo:one().
** exception error: this_is_twelve
     in function  foo:twelve/0 (foo.erl, line 49)
     in call from foo:eleven/0 (foo.erl, line 45)
     in call from foo:ten/0 (foo.erl, line 41)
     in call from foo:nine/0 (foo.erl, line 37)
     in call from foo:eight/0 (foo.erl, line 33)
     in call from foo:seven/0 (foo.erl, line 29)
     in call from foo:six/0 (foo.erl, line 25)
     in call from foo:five/0 (foo.erl, line 21)

Note that the outermost four entries are absent from the stack trace, and only the eight innermost ones remain.

Eight is just the default value. You can change it by calling erlang:system_flag/2 with backtrace_depth. (It returns the old value.)

2> erlang:system_flag(backtrace_depth, 10).
8
3> foo:one().                              
** exception error: this_is_twelve
     in function  foo:twelve/0 (foo.erl, line 49) 
     in call from foo:eleven/0 (foo.erl, line 45)
     in call from foo:ten/0 (foo.erl, line 41)
     in call from foo:nine/0 (foo.erl, line 37)
     in call from foo:eight/0 (foo.erl, line 33)
     in call from foo:seven/0 (foo.erl, line 29)
     in call from foo:six/0 (foo.erl, line 25)
     in call from foo:five/0 (foo.erl, line 21)
     in call from foo:four/0 (foo.erl, line 17)
     in call from foo:three/0 (foo.erl, line 13)

This is foo.erl. The x atoms are there to prevent the function calls from becoming tail calls, which would mean that the caller's stack frame would be removed from the stack trace.

-module(foo).
-compile(export_all).

one() ->
   two(),
   x.

two() ->
   three(),
   x.

three() ->
   four(),
   x.

four() ->
   five(),
   x.

five() ->
   six(),
   x.

six() ->
   seven(),
   x.

seven() ->
   eight(),
   x.

eight() ->
   nine(),
   x.

nine() ->
   ten(),
   x.

ten() ->
   eleven(),
   x.

eleven() ->
   twelve(),
   x.

twelve() ->
   error(this_is_twelve),
   x.
like image 62
legoscia Avatar answered Dec 05 '25 01:12

legoscia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!