Julia throws additional LoadError during exception handling

I’m not really sure if this is the right place for this question, so please let me know where I should be if this is not the right place.

I’m new to Julia, and I am writing some scripts that I’d like to use from the Linux command line. This works all fine, but when I included some exception handling into my script I found that that whenever I throw an exception Julia throws an additional LoadError So for example if I run a script containing only the following line:

throw(DivideError())

I get the both a DivideError (which I want) and a LoadError (Which I don’t want) when I run the script:

$ julia throwError.jl
ERROR: LoadError: DivideError: integer division error
Stacktrace:
 [1] top-level scope at /path/throwError.jl:1
 [2] include(::Function, ::Module, ::String) at ./Base.jl:380
 [3] include(::Module, ::String) at ./Base.jl:368
 [4] exec_options(::Base.JLOptions) at ./client.jl:296
 [5] _start() at ./client.jl:506
in expression starting at /path/throwError.jl:1

Can somebody explain what is happening here, and how I can prevent the LoadError?

2 Likes

Hi Jonas! You provided a concise example, which makes it so much easier to help.

Julia runs the code in order to load it. If you put the throw() inside a function, then Julia will run the function definition, but it won’t run the function that gets defined. You won’t see the DivideError until later, when you call the function. So:

function suspicious_fry(x)
    throw(DivideError())
    x
end
2 Likes

in short, this is happening because you’re throwing in global scope, which probably is not a realistic scenario.

Hi aldogert,

Thank you for your answer. It is not so much that I have a problem, it’s more that I try to understand how Julia works. For me throwing exceptions works fine. I was just wondering why the DivideError is wrapped by a LoadError.

Putting the throw() inside a function changes the stacktrace slightly but doesn’t change the error that is thrown. I asked this question as well on stackoverflow and somebody there pointed me to this pull request on github. What I understood from it is that Julia wraps exception throws in a LoadError as a way to show the stacktrace, but that they hope to deprecate this behavior at some point by improving backtracing in general.

But maybe somebody who has a better understanding of this, can phrase it more clearly than me.

Hi Jonas. Maybe another way to understand this is to think about the Julia code for include(). It would look like this:

function include(filename)
    open(filename) do ofile
        for line in ofile
            try
                run(line)
            catch y
                throw(LoadError(y))
            end
        end
    end
end

So run(line) creates a DivideError, and then it gets caught and passed to the user as the reason loading wasn’t possible.

1 Like

Hi Aldogert, Thanks for your code example. It made things more me clear for me.

However, I still think its peculiar that the catch y throw(LoadError(y)) is/was necessary to show the line numbers in the stack trace (at least that is what I understood from the PR).

1 Like

How about this, two files:

second.jl throws the exception only if the global run flag is set:

function panic_at_the_disco()
    throw(DivideError())
end

if run == true
    panic_at_the_disco()
end

The main file (first.jl):

run = false
include("second.jl")

try
    println("*******************************")
    println("Calling panic...")
    panic_at_the_disco()
catch ex
    println("Exception caught: $(typeof(ex))")
    println()
end

try
    println("*******************************")
    println("Running panic during include...")
    global run = true
    include("second.jl")
catch ex
    println("Exception caught: $(typeof(ex))")
    if ex isa LoadError
        println("Caused by: $(typeof(ex.error))")
    end
    println()
end

Output of running first.jl:

julia> include("first.jl")
*******************************
Calling panic...
Exception caught: DivideError

*******************************
Running panic during include...
Exception caught: LoadError
Caused by: DivideError

So include() wraps any exception thrown when loading/running the file in a LoadError but you can get the original error by accessing ex.error.

1 Like