Is it possible to get an exception message as a string?

So, for language interop reasons, I’d like to translate Julia exceptions into a different kind of error. In the C API, it is pretty clear that jl_exception_occurred is what to use to check if an exception occurred or not. But, if an exception has occurred, I haven’t found it clear how to extract the error message from it. Some exceptions seem to have the msg field, but others (like DomainError) do not.

Is it possible to get the message of an arbitrary exception as a string? For DomainError thrown by sqrt(-1), this would be:

ERROR: DomainError:
sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)).
 in sqrt(::Int64) at ./math.jl:211

Thanks!

You can call sprint(showerror, e) to get the message of an exception in string form, or sprint(showerror, e, backtrace()) in the context of a catch block to print additional information extracted from the backtrace.

For example, the sqrt message you quoted is printed by a special case of showerror given a backtrace indicating that the DomainError came from a sqrt call.

8 Likes

Thanks, stevengj! However, if I do this:

try
  sqrt(-1)
catch e
  bt = backtrace()
  msg = sprint(showerror, e, bt)
  println(msg)
end

I don’t get the full error message, what I see is:

DomainError:
 in backtrace() at ./error.jl:26
 in backtrace() at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
 in include_from_node1(::String) at ./loading.jl:488
 in include_from_node1(::String) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
 in process_options(::Base.JLOptions) at ./client.jl:262
 in _start() at ./client.jl:318
 in _start() at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?

Is there a way to get the full message?

Ah, okay, so this does work (sort of, see below) if I use catch_backtrace() instead of backtrace(). However, if I try and encapsulate the whole thing in a function, it seems to no longer work.

To be clear, this works and gives me the full message:

try
  sqrt(-1)
catch e
  bt = catch_backtrace()
  msg = sprint(showerror, e, bt)
  println(msg)
end

Whereas this does not:

function test()
  try
    sqrt(-1)
  catch e
    bt = catch_backtrace()
    msg = sprint(showerror, e, bt)
    println(msg)
  end
end

test()
1 Like

By default Julia inlines most or all of the sqrt call when the block is inside a function. Hence the sqrt symbol is missing from the backtrace, and showerr doesn’t get the hint to add the detailed message. You could turn off inlining if you really want the message.

1 Like