Better runtime backtraces

crystal has the ability to generate very descriptive backtraces at compile time:

$ cat
def go1

$ crystal build --error-trace

5 | go1
Error: instantiating ‘go1()’


2 | go3
Error: undefined local variable or method ‘go3’ for top-level

Did you mean ‘go1’?

I had a thought that maybe runtime exception traces, like this one:

$ cat
raise “BOOM”

$ crystal
Unhandled exception: BOOM (Exception)
from in ‘__crystal_main’
from /usr/share/crystal/src/crystal/ in ‘main_user_code’
from /usr/share/crystal/src/crystal/ in ‘main’
from /usr/share/crystal/src/crystal/ in ‘main’
from __libc_start_main
from _start
from ???

could possibly be aumented so that they show more information, like looking up the source code on the lines of the backtrace, at runtime. Thoughts?

This might help debugging during development, but it wouldn’t be useful in production. The additional verbosity would fill up logs and provide no benefit. Often source code wouldn’t be available anyway in the runtime environment. And these enhancements for runtime errors would add a bunch of additional code to every Crystal program, again with often no real gain.

It would be possible though to have enhanced backtraces for development. This should be pretty easy to implement, and could even go entirely into user code. Essentially, you just need to override Callstack.print_frame and enhance the frame output.

An alternative solution would be to pipe stderr through a program that enhances the backtraces. That might actually be easier to implement and it’s more flexible because it doesn’t need to be activated at compile time and you can even enhance backtraces from logs.

1 Like’s crash handler would be an example for parsing the error output from a Crystal program and enhancing it:


Thanks. I’ll try making one a shard and if I really like it propose it for the stdlib (in non release compiles only perhaps? :)