# Please stop using \`error\` and \`ErrorException\` in packages (and Base)

**URL:** https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096
**Category:** General Usage
**Tags:** error
**Created:** [July 2, 2018, 6:37am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096 "2018-07-02T06:37:35Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [July 2, 2018, 6:37am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/1 "2018-07-02T06:37:35Z")

</div>

In julia we like to distinguish different things using different types (exceptions are one such thing).  
In most languages they also like to distinguish different exceptions with different types.

In particular in julia

```julia
try
    foo()
catch err
    if err isa BarError
            # Handle it
    elseif err isa BlargError
            # Handle that
    else
           rethrow()
    end
end

```

Saying `error("it is borked because the Blarg is flumoxed")` causes an `ErrorException` to be thrown.  
This is an incredibly unhelpful error, typewise.  
You can;t work out what threw it or why.  
So you can’t handle it safely.

`error` exists for when you can’t be bothered declaring an exception type.  
Or working out which existing one to use.  
It belongs in user-scripts, and quick prototypes.  
It doesn’t belong in registered packages, and it particularly doesn’t belong in Standard Libraries / `Base`  
Most gone now. However, the `run` command still throws one ([https://github.com/JuliaLang/julia/pull/27900](https://github.com/JuliaLang/julia/pull/27900)).

I suggest that `ErrorException` should be treated as if it were an uncatchable exception type.

I suspect our over reliance on using `error` might come back to prior experiences we have using other languages where declaring your own exception type is difficult.  
But in julia it is easy

`struct MyError <:Exception end`  
or

```julia
struct MyErrorWithMsg <:Exception
    msg::String
end

```

There is also `@assert` for things that a programmer errors.  
So you can replace

```julia
if val == true
     # do it
elseif val==false
     # do not do it
else
     error("This should never happen") 
end

```

With

```julia
if val == true
     # do it
elseif val==false
     # do not do it
else
     @assert(false, "This should never happen") 
end

```

Which is clearer.

* * *

I am not saying I am perfect, I have packages where I was lazy and used `error`,  
rather than using the right exception type.  
But lets try and clean those out now, while we are getting ready for 1.0.

Save `error` for end-users; keep it out of your packages

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [July 2, 2018, 6:58am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/2 "2018-07-02T06:58:48Z")

</div>

One solution which involves changing the standard library might be to

- make a add a type param for `ErrorException{N} <: Exception` in `Base`.
- deprecate `error` for `@error`
- define `@error(msg)` to do `throw(ErrorException{nameof(@ __MODULE__ )}(msg)`

At least then it would be apparent (in the type) what module was throwing an error.  
Also using `@error` would have nice symmetry with `@warn` and `@info`

I think this is a non-breaking change? Since `ErrorException{N} <: ErrorException`.  
Maybe not since they are not equal. It is an almost nonbreaking change

Still not as good as throwing errors with semantic types

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [July 2, 2018, 7:05am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/3 "2018-07-02T07:05:59Z")

</div>

I tend to use exceptions to propagate information towards the user, not for control flow. So while I see the value of fine-grained exceptions, especially if running in an application which can decide what to handle and what to fail on, I am curious what your use case is for enforcing a fine-grained distinction.

As for the occasional `ErrorException`, I find the stack trace has the information I need.

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [July 2, 2018, 7:19am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/4 "2018-07-02T07:19:36Z")

</div>

> I see the value of fine-grained exceptions, especially if running in an application which can decide what to handle and what to fail on

Thing is, when you are writing a **package you don’t know** if the package is being used by a project which can decide what to handle and what to fail on.

Packages are for reuse.  
That is why I am saying in packages, (not nesc in general),  
avoid using `error`.  
In a application (in the Pkg3 sense) go wild, use what ever error handling you want.

Like yes, the stack information always has what you need,  
and the message often also has useful info.  
But we don’t want to be doing exception handling via programatically inspecting the stack, or regexing the message

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [July 2, 2018, 7:38am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/5 "2018-07-02T07:38:28Z")

</div>

> [@oxinabox](#):
>
> when you are writing a **package you don’t know** if the package is being used by a project which can decide what to handle and what to fail on

I agree, but I expect that if someone depends on handling exceptions, this part of the API can be always be refined as a feature request.

I think it is good to know the exception types in `Base` and use them when applicable, but in case they don’t fit, I am not sure I would introduce a new exception type unless there is a strong reason to do so.

Also, categorizing an exception can be a bit fuzzy. Eg there is considerable overlap between `ArgumentError` and `DomainError`, so very fine-grained handling may be tricky.

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [July 2, 2018, 7:46am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/6 "2018-07-02T07:46:20Z")

</div>

> [@Tamas\_Papp](#):
>
> I agree, but I expect that if someone depends on handling exceptions, this part of the API can be always be refined as a feature request.

Of-course. I do appreciate feature-request driven development (particularly as a method to avoid gold-plating)  
It is worth remembering that changing your exception types is a breaking change.  
So it is nice to be proactive and get it right the first time.

> I think it is good to know the exception types in Base and use them when applicable, but in case they don’t fit, I am not sure I would introduce a new exception type unless there is a strong reason to do so.

Can you expand on why you are not sure introducing new exceptions is good?

> Also, categorizing an exception can be a bit fuzzy. Eg there is considerable overlap between ArgumentError and DomainError, so very fine-grained handling may be tricky.

Indeed, though IIRC in the particular case it was actually purely an optimization thing. Up until fairly recent compiler versions there was an overhead to having a field in your exception, that was hurting critical inner loop somewhere in `Base`. So `DomainError` unlike `ArgumentErrror` had no message field.  
Anyway I maintain either is better than `ErrorException` since they tell you something is wrong with the functions inputs  
Can always handle both via `||` or `Union`

---

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [July 2, 2018, 8:00am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/7 "2018-07-02T08:00:58Z")

</div>

See  
[https://github.com/JuliaLang/julia/issues/7026](https://github.com/JuliaLang/julia/issues/7026)  
for a lot of discussion on this. Coming from C# I also thought about using exceptions in Julia for control flow but it seems that there is no consensus on this being Julian.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [July 2, 2018, 8:30am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/8 "2018-07-02T08:30:37Z")

</div>

> [@oxinabox](#):
>
> Can you expand on why you are not sure introducing new exceptions is good?

If someone wants to dispatch on it, I would certainly introduce a type, but I would wait until then. There is no strong reason not to do so. Unless I am 90% confident that I need to dispatch on it, I consider a specific exception type premature. There are already

```julia
julia> length(subtypes(Exception))
58

```

in `Base` alone.

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [July 2, 2018, 8:45am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/9 "2018-07-02T08:45:22Z")

</div>

> Unless I am 90% confident that I need to dispatch on it, I consider a specific exception type premature.

I think we are just going to have to disagree on that one.  
**And that is Ok.** 🙂

> julia\> length(subtypes(Exception))  
> 58

For reference in 0.7, there are only 27 exported Exceptions in Base and core  
It is worth excluding the ones that are not exported.

## All exceptions

```julia-auto
julia> exceptionnames = Set(nameof.(subtypes(Exception)))
Set(Symbol[:SystemError, :PkgTestError, :DimensionMismatch, :ErrorException, :InexactError, :OverflowError, :UndefRefError, :UndefVarError, :CapturedException, :CodePointError … :ArgumentError, :WrappedException, :BatchProcessingError, :MissingException, :CommandError, :UVError, :SimdError, :PkgError, :PosDefException, :OutOfMemoryError, :ReadOnlyMemoryError])

julia> length(ans)
55

```

## counting exported and non-exported names from Base and Core

```julia-auto
julia> exceptionnames ∩ (Set(names(Base; all=false)) ∪ Set(names(Core; all=false)))
Set(Symbol[:SystemError, :InterruptException, :DivideError, :DimensionMismatch, :KeyError, :ErrorException, :InexactError, :TypeError, :MethodError, :SegmentationFault … :UndefVarError, :CapturedException, :InvalidStateException, :AssertionError, :StringIndexError, :StackOverflowError, :OutOfMemoryError, :UndefKeywordError, :EOFError, :BoundsError, :ReadOnlyMemoryError])

julia> length(ans)
27

```

---

<div class="post-metadata">

### Author: ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)
#### Post date: [July 2, 2018, 9:53am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/10 "2018-07-02T09:53:02Z")

</div>

btw, what’s the difference between error and exception?

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [July 2, 2018, 9:56am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/11 "2018-07-02T09:56:15Z")

</div>

`error` is a function that corresponds to `error(msg) = throw(ErrorException(msg))`.

`Exception` is an abstract type, that is the parent (/ancestor) of all exception types,  
including `ErrorException`, as well as say `BoundsError` etc.

---

<div class="post-metadata">

### Author: ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)
#### Post date: [July 2, 2018, 9:58am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/12 "2018-07-02T09:58:32Z")

</div>

I mean, there are `SystemError` and `InterruptException`

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [July 2, 2018, 10:04am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/13 "2018-07-02T10:04:09Z")

</div>

Nothing, there is no meaningful difference/consistent convention.  
It might be nice if there was, but there isn’t.

---

<div class="post-metadata">

### Author: ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)
#### Post date: [July 2, 2018, 10:16am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/14 "2018-07-02T10:16:46Z")

</div>

Yeah, `SegmentationFault` even not error nor exception…

(for error vs exception, just found a section `Errors and exceptions` in [Exception Class (System) | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/system.exception?view=netframework-4.7.1))

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [July 2, 2018, 10:32am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/15 "2018-07-02T10:32:51Z")

</div>

I’m wondering if you have some good examples of errors thrown where it makes sense to use different exception types and then have code handling those.

Right now, I can only think of cases where you actually use exceptions as control flow - of which I’m not a big fan. There are also the cases for cutting down down on boilerplate (e.g. out of bounds error follow a certain structure + print out, which can be implemented one time as part of the BoundsError type) - but that one is missing the handling of the exception part.

I consider most of my errors as fatal and follow the philosophy of only checking/catching errors where they occur.  
Exception to this is test code: code is easier to test for certain errors, when the different exceptions that can occur have different types, instead of checking the string of the `ErrorException`. But only working with ErrorException seems acceptable albeit less clean, since even if you use different types for the exceptions, you should still check the message 😉

---

<div class="post-metadata">

### Author: ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)
#### Post date: [July 2, 2018, 12:41pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/16 "2018-07-02T12:41:43Z")

</div>

I just scanned a few of my packages for `error()` calls (which I use extensively) and found several use cases:

1. Programmer error. Could be replaced with `@assert`, but I don’t really see the difference since both are essentially unrecoverable.
2. Bad arguments, but not user fault. For example, someone can try to differentiate function that we don’t currently support.
3. Bad environment. E.g. trying to load binary dependency that is missing from the system (assuming the package can’t be used without it).

In all these cases I want an error message to be propagated directly to the user, so `ErrorException` is used to indicate that something went terribly wrong and there isn’t much you can automatically do about it.

On the other hand, I can clearly see the advantage of using specific exception types when:

1. Working with external resources, e.g. missing file, failing network or bad user input are all _recoverable_.
2. For control flow, e.g. to skip bad records in a list or stop doing writing to a storage when it’s full (although I’d really love if we had something like Common Lisp’s [condition system](https://en.wikibooks.org/wiki/Common_Lisp/Advanced_topics/Condition_System)).

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [July 2, 2018, 12:43pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/17 "2018-07-02T12:43:33Z")

</div>

> [@dfdx](#):
>
> For control flow, e.g. to skip bad records in a list

I think that the idiomatic way to do this in Julia is using small unions, not unlike `tryparse`.

---

<div class="post-metadata">

### Author: ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)
#### Post date: [July 2, 2018, 2:49pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/18 "2018-07-02T14:49:26Z")

</div>

> [@Tamas\_Papp](#):
>
> I think that the idiomatic way to do this in Julia is using small unions, not unlike `tryparse` .

It only works when control decision is taken exactly one level higher than the function returning a small union, e.g.:

```julia
function sum_numbers(lines)
    s = 0
    for line in lines
        res = tryparse(Int, line)
        if res != nothing
            s += res
        end
    end
    return s
end

```

But it’s less convenient when you have several levels of invocation, e.g.:

```julia
function process_dir(dirname)
    processed_files = 0
    for file in readdir(dirname)
        file_ok = process_file(file)
        if file_ok 
            processed_files += 1
       end
    end
    println("Processed $processed_files files")
end

function process_file(file)
    lines = ...
    failed = false
    for line in lines
        res = tryparse(line)
        if res != nothing
            ...
        else
            failed = true
            break 
        end
    end
    return !failed
end

```

which can be simplified to:

```julia
function process_dir(dirname)
    processed_files = 0
    for file in readdir(dirname)
        # we still need a check on the control flow level
        try
            process_file(file)
            processed_files += 1
       catch e
           if e isa ArgumentError
               # ignore
           else
               rethrow()
           end
       end
    end
    println("Processed $processed_files files")
end

function process_file(file)
    lines = ...
    for line in lines
        # we don't need special checks in intermediate levels since exception  
        # will unroll stack anyway 
        res = parse(line)
        ...
    end
end

```

---

<div class="post-metadata">

### Author: ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)
#### Post date: [July 2, 2018, 2:58pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/19 "2018-07-02T14:58:42Z")

</div>

I think one of the problems for me at least is that it can be hard to know what the appropriate exception type is. I find myself using `ArgumentError` quite often… in fact I’d go as far as to say usually if I bother to explicitly throw an exception it’s an `ArgumentError`.

For me this problem is in no way specific to Julia. I also tend to really dislike `try` `catch` constrcuts, I usually feel that either my code should run without error or it should not run at all.

---

<div class="post-metadata">

### Author: ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)
#### Post date: [July 2, 2018, 3:25pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/20 "2018-07-02T15:25:35Z")

</div>

> [@dfdx](#):
>
> - Bad arguments, but not user fault. For example, someone can try to differentiate function that we don’t currently support.
> - Bad environment. E.g. trying to load binary dependency that is missing from the system (assuming the package can’t be used without it).

For both these cases, it is easy to imagine situations where I might want to catch the exception:

For missing binary dependencies, the package that depends on your package might provide a workaround, so that the end-user does not need to be bothered. Or it might want to rewrite the error message, because the end-user does not want to know about the nitty gritty internals of your package.

Your example with differentiation is even more salient: A package that uses differentials might want to try multiple strategies; e.g. try symbolic before AD, but only if symbolic (1) works and (2) the expressions stay reasonably small; so your user, who is a package author, may reasonably want to catch this.

An example I dealt with very recently are bad llvm instructions: On archlinux 0.6.3 binaries, I get the unrecoverable (crash julia) `LLVM ERROR: Cannot select: intrinsic %llvm.x86.aesni.aeskeygenassist`. You know, I’d like to catch that and fall back on a software implementation. And “this version of llvm does not know whether your CPU supports whatever you are trying to do” looks like the same ballpark of error as your examples. (but making this catchable is probably harder than julia-issued “error”, as evidenced by julia crashing)

[Next page](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096.md?page=2)
