# 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:** 10\
**Page:** 2

<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, 3:34pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/21 "2018-07-02T15:34:51Z")

</div>

> [@foobar\_lv2](#):
>
> For both these cases, it is easy to imagine situations where I might want to catch the exception:

Yep, and in these rare cases you still can catch `ErrorException`.

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [July 2, 2018, 4:56pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/22 "2018-07-02T16:56:27Z")

</div>

EDIT: I only fixed typos since the first version of this post. But, I see this bumps the post to the most recent. Unfortunately, there does not seem to be a toggle to prevent this (because “none of our paying customers ever asked for this”… fair enough)

I have some sympathy. Recently I used a Python wrapper of a MySQL library. Probably for lack of time, the author coarse-grained the possible exceptions and included a catchall. For whatever reason the error strings were not useful. I was quite frustrated. Of course, it took no knowledge of Python or MySQL for me to fix it in the Python source (I should give it back some day.)

Even if the error is not caught, using the correct exception can more consistently and reliably convey information than a string alone can; a string constructed however the author saw fit.

Regarding `@assert`, it’s clear that the ultimate arbiters here understand that (from [c2.com](http://c2.com))

> An assertion is a boolean expression at a specific point in a program which will be true unless there is a bug in the program.

It should be possible to easily disable assertions to test production code. Exceptions should never be used in place of assertions. They play different roles and should not be confused.

But, `@assert` will not get this clearly defined role till at least v1.1. If I read the discussions (several threads) correctly, care was taken so that `@assert` can be used correctly in the future without breaking v1.0 compatibility. (Many popular languages did not have proper assertions at the time of first stable release.)

---

<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 3, 2018, 7:23am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/23 "2018-07-03T07:23:37Z")

</div>

> [@foobar\_lv2](#):
>
> the package that depends on your package might provide a workaround, so that the end-user does not need to be bothered

IMO such workarounds are just trouble in the long run. They are usually procedural (not declarative), and are prone to bit rot much more than “usual” code. I recognize that sometimes they are necessary, but the goal should be to get rid of them as quickly as possible.

> [@foobar\_lv2](#):
>
> 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.

Again, if a package advertises that it does symbolic AD, why would it not work? That would be a bug. Using the exception handling system to work around bugs is sometimes necessary, but should be considered the durian of code smells.

---

<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 3, 2018, 7:29am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/24 "2018-07-03T07:29:40Z")

</div>

> [@dfdx](#):
>
> ```julia
> for line in lines
> res = tryparse(line)
> if res != nothing
> ...
> else
> failed = true
> break 
> end
> end
> end
> 
> ```

I would probably code this as

```julia
function process_file(file)
    lines = ...
    for line in lines
        res = tryparse(line)
        res ≡ nothing && return true
        ...
    end
    false
end

```

which I consider rather simple, but I see your point. Some languages do encourage conditions for control flow, and probably Common Lisp was the language that took it to the extreme with restarts, eg see [Practical Common Lisp](http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html) for a nice example. I was kind of missing that when I started using Julia, but now I consider these misfeatures, as they lead to code which require a lot of non-local convoluted reasoning.

---

<div class="post-metadata">

**Author:** ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)\
**Post date:** [July 3, 2018, 8:15am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/25 "2018-07-03T08:15:11Z")

</div>

> [@Tamas\_Papp](#):
>
> I am curious what your use case is for enforcing a fine-grained distinction.

I humbly think it is case of every more complex code with longer support and/or with bigger team.

> [@Tamas\_Papp](#):
>
> There are already
> 
> ```julia
> julia> length(subtypes(Exception))
> 58
> 
> ```
> 
> in `Base` alone.

I am not julian yet so maybe I see it wrong but I see as problem:

```julia
length(filter(isabstract, subtypes(Exception) )) == 1 

```

so there is clearly no hierarchy here…

---

<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 3, 2018, 9:05am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/26 "2018-07-03T09:05:03Z")

</div>

Here is one in the wild:

[https://github.com/malmaud/TensorFlow.jl/blob/459b5450917be40d2fa14bfd988d7877332bc62f/src/shape\_inference.jl#L44-L65](https://github.com/malmaud/TensorFlow.jl/blob/459b5450917be40d2fa14bfd988d7877332bc62f/src/shape_inference.jl#L44-L65)

If the shapes are incompatible, then it throws with useful error message.  
A `try_unify` couldn’t give a message saying what failed, just that something did.  
(While I like that pattern for simple cases, I think for complicated cases it only can go so far.)

That exception can be thrown at a bunch of different times, basically anytime the shape inference is invoked.  
It is caught, at one place:  
[https://github.com/malmaud/TensorFlow.jl/blob/9a2b5a1b81481eca197f16ec38e8017c7e72ac5f/src/run.jl#L142-L154](https://github.com/malmaud/TensorFlow.jl/blob/9a2b5a1b81481eca197f16ec38e8017c7e72ac5f/src/run.jl#L142-L154)  
Which is a function called during `run` to actually check the inputs match the placeholders.  
If they do not then it throws a new richer error message that also says which input failed to match.

---

<div class="post-metadata">

**Author:** ![samoconnor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samoconnor/32/1802_2.png) [@samoconnor](https://discourse.julialang.org/u/samoconnor)\
**Post date:** [July 3, 2018, 11:01am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/27 "2018-07-03T11:01:14Z")

</div>

> [@oxinabox](#):
>
> I suggest that `ErrorException` should be treated as if it were an uncatchable exception type.

Here is a related (out of date) attempt to implement uncatchable exceptions:

> <https://github.com/JuliaLang/julia/pull/15906>
>
> See #15514
> \### Interface
> 
> \`try\` causes ordinary errors to disappear as usual:
> 
> …\`\`\` julia
> julia\> try error("foo") end
> \`\`\`
> 
> \`try\` no longer catches fatal errors:
> 
> \`\`\` julia
> julia\> try foo end
> ERROR: UndefVarError: foo not defined
> in eval(::Module, ::Any) at ./boot.jl:236
> \`\`\`
> 
> The \`isfatal\` function decides which errors are fatal:
> 
> \`\`\` julia
> isfatal(error) = false
> isfatal(::StackOverflowError) = true
> isfatal(::OutOfMemoryError) = true
> isfatal(::UndefVarError) = true
> \`\`\`
> 
> Handling of fatal exceptions can be reenabled for a particular stack frame (e.g. for the REPL, \`@test\_throws\`, RPC, etc...):
> 
> \`\`\` julia
> julia\> function f()
> Base.enable\_catch\_fatal()
> try foo catch ex println("Caught: $ex") end
> Base.disable\_catch\_fatal()
> bar
> end
> 
> julia\> f()
> Caught: UndefVarError(:foo)
> ERROR: UndefVarError: bar not defined
> \`\`\`
> \### Implementation
> 
> A call to \`rethrow\_if\_fatal\` is inserted at the top of the \`catch\` block:
> 
> \`\`\` julia
> julia\> expand(:(try foo end))
> 
> :($(Expr(:thunk, Toplevel LambdaInfo thunk
> :(begin
> $(Expr(:enter, 6)) # REPL\[1\], line 1:
> GenSym(0) = foo
> $(Expr(:leave, 1))
> return GenSym(0)
> 6:
> $(Expr(:leave, 1))
> (top(rethrow\_if\_fatal))($(Expr(:the\_exception)))
> return
> end))))
> \`\`\`
> 
> \`rethrow\_if\_fatal()\` rethrows fatal exceptions unless, e.g., the REPL wants to catch fatal exceptions at a particular stack frame.
> 
> \`\`\` julia
> rethrow\_if\_fatal(error) = isfatal(error) && ccall(:jl\_rethrow\_fatal, Void, ())
> \`\`\`
> 
> The REPL calls \`Base.enable\_catch\_fatal()\` in \`eval\_user\_input\`. This allows it to catch and display fatal errors as usual.

---

<div class="post-metadata">

**Author:** ![taqtiqa-mark](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taqtiqa-mark/32/4383_2.png) [@taqtiqa-mark](https://discourse.julialang.org/u/taqtiqa-mark)\
**Post date:** [May 2, 2019, 11:41am UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/28 "2019-05-02T11:41:56Z")

</div>

Hi, I’m trying to understand the best practice in situations such as where [StatsBase.jl](https://github.com/JuliaStats/StatsBase.jl/blob/master/src/statmodels.jl#L10), uses `error(...)` liberally.

Is this type of usage of `error(...)`frowned upon?  
If so what would best julia practice look like?  
How would you write a test for this change so that if someone reverted it, there would be some indication?

Appreciate any hints. tips and suggestions.

---

<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:** [May 2, 2019, 12:45pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/29 "2019-05-02T12:45:25Z")

</div>

> [@taqtiqa-mark](#):
>
> Is this type of usage of `error(...)` frowned upon?

In this particular case, IMO `MethodError` would work fine and defining a method saying there is no method is kind of redundant. I am aware that some packages do this though, presumably to help the user.

> [@taqtiqa-mark](#):
>
> If so what would best julia practice look like?

Here, I would recommend just not defining a method.

> [@taqtiqa-mark](#):
>
> How would you write a test for this change so that if someone reverted it, there would be some indication?

See [`Test.@test_throws`](https://docs.julialang.org/en/v1/stdlib/Test/#Test.@test_throws).

Note that these are just my stylistic preferences. Some older Julia packages were written at a time when best practices for Julia code were still being explored, and may reflect a style people no longer use, or not that widely. Make sure you check with the maintainers before making pure style PRs, are not universally encouraged (benefit vs cost of reviewing etc).

---

<div class="post-metadata">

**Author:** ![taqtiqa-mark](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taqtiqa-mark/32/4383_2.png) [@taqtiqa-mark](https://discourse.julialang.org/u/taqtiqa-mark)\
**Post date:** [May 2, 2019, 8:34pm UTC](https://discourse.julialang.org/t/please-stop-using-error-and-errorexception-in-packages-and-base/12096/30 "2019-05-02T20:34:36Z")

</div>

Thanks @Tamas_Papp, appreciate you sharing your thoughts and suggestions.

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