In python you can define an exception hook such that all errors go through it and you can print them as you’d like. I would like to the same in Julia, but haven’t found a way yet.
I haven’t found good docs on how errors are handled internally, but going through the code I’ve found functions like show_backtrace and showerror in Base.errorshow.jl and display_error in Base.client.jl as well as other similarly named functions.
I can re-define this to print out formatted error messages as above, but there’s several things I’m not clear with:
what calls show_backtrace and errorshow? Does it depend on where the code is run (e.g. in VSCode or in the Julia app?). I can re-define show-backtrace and errorshow, but ideally I’d like to intercept error messages before.
what prints out LoadErrors? It seems to bypass show_backtrace and errorshow as I can’t find a way to style that.
Accessing locals: in python’s exceptions hook you have access to locals at all levels in the callstack (see second image above). I know there’s Base.@locals but that only gives the locals where the macro is used. Is there a way to get locals at each frame in a stacktrace or backtrace?
Julia’s errors come with hints provided by Base.Experimental.show_error_hints, which is really nice. However when I try to use show_error_hints in my re-defined errorshow functions it doesn’t give any hint (it returns nothing). Is there a way to access error hints?
Yes, it depends on the IDE. In the REPL it’s handled by the following line: https://github.com/JuliaLang/julia/blob/2338f5d3040ced10d69f4d15cca5fdca03364d9a/stdlib/REPL/src/REPL.jl#L291. Note however that refining any of these functions is type piracy and strongly discouraged, since it can result in inconsistent behavior and excessive invalidations. Base.Experimental.register_error_hint is how additional hints are intended to be added.
They should go through the REPL as well. Do you have an example?
show_error_hints always returns nothing, the hints are printed to the supplied IO object. You can of course use sprint to get the output as a string or take a look at its source code if you want each separate hint.
Note however that refining any of these functions is type piracy and strongly discouraged
Arrrr!
I would very much prefer not having to do that! But is there an alternative to it like python’s exception hook?
If lines like Base.invokelatest(Base.display_error, errio, val) that you’ve send above (and similar ones e.g. in VSCode’s Julia Extension) are what prints out the error, then I’m guessing I have to re-define Base.display_error?
At any rate, it wouldn’t be done by default in my package, it would be an option that users have to explicitly activate and I will warn them that it’s a hacky solution.
There is Base.Experimental.register_error_hint, but you seem to already have discovered that. Your projects looks very exciting, so if you have a concrete proposal for what kind of hooks you would need, I think the core devs would be open to discuss potential changes to base.
display_error should end up calling showerror, so redefining that should have similar effects.
Perhaps a solution would be to push your own display to the top of the display stack. Literate.jl uses pushdisplay and popdisplay to catch display calls. I believe something similar is done for e.g. the plot pane in the VS code extensions.
AbstractDisplay is something that I didn’t know about, and it might be very useful in the future, but as far as I can tell I can’t make much use of it here. Thanks anyway!
This is an exciting project to see being worked on!
IMO, one of the main disadvantages of Julia in terms of user experience, apart form TTFX, is that error messages are often verbose and intimidating.
It is not uncommon to receive three-page nested error messages when (ab)using DataFrames.jl, for example, and I think this is a significant problem for Julia’s general adoption. Especially for those coming from languages like Python, whose traceback messages are (mostly) very succinct and lucid, such long error messages can be scary and hard to glean information from.
I don’t think it’s appropriate for Term.jl’s style of displaying error messages to become Julia’s default, but I would love to see Julia’s error messages become something in between what they are now and the proof-of-concept shown in this post.
I hope the Julia devs agree that providing an interface for intercepting and display error messages is a good investment. I’m thinking this might also be a boon for HTML-based front-ends like Pluto.jl.