Getting a stack trace with function argument values

question

#1

When an error is not caught, Julia shows a stack trace with the method signatures. This is informative, but sometimes the actual arguments to the functions would be very useful too. Is there a way to have them shown? Using 0.5.0.


How do you use debuggers?
#2

No. This is the job of the debugger. See my replies in Inspecting the stack


#3

I was reading the manual on stack traces and thought of this issue again. My understanding is that I can get the stack trace with try ... catch, eg in this MWE:

using Compat                    # for two-argument DomainError in 0.6

bad(x) = throw(DomainError(x, "I don't like this value."))

st = try
    bad(1)
catch
    catch_stacktrace()
end

Is there a way of extracting 1 (=x) and "I don't like this value." from it?

Also, if I happened to just run into an error, and was not prepared with a try ... catch like above, there is no way I can extract this information ex post; is this correct?


#4

An exception can store whatever state it wants and that can be retrieved by catching the exception and inspecting it.

The stacktrace itself does, however, not store an instance of the exception.


#5

What is the correct way to use the arguments of DomainError then? They are not displayed for uncaught errors, and it seems I cannot extract them either.

Are you suggesting that exceptions save global state somewhere? Wouldn’t this only work when the user has control over the source of the exception?

I am aware that I could

bad(x) = throw(ArgumentError("I don't like this value."))
st = try
    bad(1)
catch e
    println(e)
end

but the thing about exceptions is that I don’t usually expect them, then I may have to rerun a long, potentially nondeterministic computation to get the information about the problem.


#6

but the thing about exceptions is that I don’t usually expect them, then I may have to rerun a long, potentially nondeterministic computation to get the information about the problem.

That’d be a very nice feature for a debugger. ipython does this with %debug.


#7

You asked if you could extract the information from the DomainError. The answer is yes, if you catch it you can extract that information.

If you want to arbitrarily inspect the stack when an error got thrown, then yuyichao’s answer applies.


#8

Just to make sure I understand: is that answer “no, you can’t, it is impossible by design”? This is the impression I got from the other thread.

OTOH it should be fairly simple to do something like

julia> macro print_exception(expr)
           quote
               try
                   $expr
               catch e
                   println("Oops, got this exception:")
                   println(e)
               end
           end
       end
@print_exception (macro with 1 method)

julia> @print_exception bad(1)
Oops, got this exception:
ArgumentError("I don't like this value.")

and I wonder if the REPL could do something like this by default.


#9

What do you want to do?? The REPL IS printing the error for you by default???


#10

Ideally,

  1. I want embed information in the exception that can be used to isolate and debug the error,
  2. I want to be able to use this even if I was not prepared for the error (eg in interactive use).

Printing is fine when the conversion to text and back is sufficient, but that is not always the case (eg when non-printed digits matter).


#11

Yes, this is just a normal exception, for example a BoundsError embeds the array and what index was accessed.

When an exception is thrown, the REPL prints the exception and the exception can display the error in whatever way it wants.

What you can’t do is to poke around in the local state of an arbitrary location that throws an arbitrary exception. For that you need something like a debugger.


#12

If you mean you want to access it in a similar fashion as ans for the result and NOT what your @print_exception is doing, then I think that’s a legit and potentially handy feature for the REPL.


#13

Yes, this would solve my problem. Thanks for clarifying.