# Good error messages

**URL:** <https://discourse.julialang.org/t/good-error-messages/105523>\
**Category:** General Usage\
**Tags:** discussion\
**Created:** [October 28, 2023, 9:11pm UTC](https://discourse.julialang.org/t/good-error-messages/105523 "2023-10-28T21:11:12Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [October 28, 2023, 9:11pm UTC](https://discourse.julialang.org/t/good-error-messages/105523/1 "2023-10-28T21:11:12Z")

</div>

I often find error messages like this impractical:

```julia
julia> only([1, 2])
ERROR: ArgumentError: Collection has multiple elements, must contain exactly 1 element

```

We don’t know what the `Collection` is, we don’t know what the `elements` are, we don’t know how many there are (only multiple). If I find this in the logs of a crashed CI run or so, where I can’t easily go in and check out runtime values, it’s unhelpful. Because of this I often find myself writing my own `only` check just so I can have a more informative error, which kind of defeats the purpose of the function.

For the above example, the message could theoretically be:

```julia
julia> only([1, 2])
ERROR: ArgumentError: [1, 2] has 2 elements, must contain exactly 1 element

```

However, I recognize that it’s hard to rewrite the error message generically.  
You could write the type instead of `Collection` but that might be a huge thing. We could print all the `elements` if there are at max let’s say five or so, but not after that as there could be way too many. For general iterators, we usually don’t know how many elements there are because `only` errors already at the second one. Etc. etc., so we end up with what I posted above.

I would like to get a discussion and sharing of strategies going, and maybe collect some ideas for changes in Julia of similarly uninformative error messages. What do other languages who are praised for their good error messages doing? Can we copy some approaches?

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [October 28, 2023, 9:36pm UTC](https://discourse.julialang.org/t/good-error-messages/105523/2 "2023-10-28T21:36:48Z")

</div>

The `only` example makes me think the idea should be to give the _proof_ of the error condition.

> [@jules](#):
>
> We could print all the `elements` if there are at max let’s say five or so, but not after that as there could be way too many.

For `only`, we need to prove it has 2 elements, no more.

> [@jules](#):
>
> You could write the type instead of `Collection` but that might be a huge thing.

It would be nice to have a Base function `abbreviated_type` to use in error messages.

* * *

In [another post](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/3) I tried Elm style errors, and Mason came up with [a macro](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/51) to use like

```julia
function f(x::Real)
    if x>= 0.0
        x + 1
    else
        @noinline_block x throw(DomainError("f requires inputs greater than 0, you gave $x which is less than 0"))
    end
end

```

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [October 28, 2023, 9:40pm UTC](https://discourse.julialang.org/t/good-error-messages/105523/3 "2023-10-28T21:40:35Z")

</div>

> [@jar1](#):
>
> the idea should be to give the _proof_ of the error condition

That’s a good idea, I was thinking more about trying to give the context in which the error occurred. I guess the two are intertwined, but yours is more terse

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 28, 2023, 10:03pm UTC](https://discourse.julialang.org/t/good-error-messages/105523/4 "2023-10-28T22:03:15Z")

</div>

> [@jules](#):
>
> `[1, 2]`

printing this may spam multiple screen (now you may want an IOBuffer and truncate), or it may even error (display wasn’t implemented properly). This is probably doable for `<:Array` but it’s I guess people didn’t have time to specialize polish the errors.

Maybe one could argument a replacement of `Collection` → argument of `only()`, but I assume the line number of the error message already tells you it’s the `only()`…

* * *

btw, there is a special case for Tuple. The `<:Array` is just hitting a fallback of trying to `iterate()` and see if the result is `nothing` or not.

```julia
julia> only((1,2))
ERROR: ArgumentError: Tuple contains 2 elements, must contain exactly 1 element
Stacktrace:

```

So yeah, I suppose you’re saying we should add a `<:Array` speailized error message

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [October 28, 2023, 10:08pm UTC](https://discourse.julialang.org/t/good-error-messages/105523/5 "2023-10-28T22:08:04Z")

</div>

This thread is not about just `only`, that was a handy example I had. But in general about strategies to write good errors in the face of uncertainty of values in generic functions. It’s kind of annoying that this aspect suffers so much when writing generic code.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [October 28, 2023, 10:39pm UTC](https://discourse.julialang.org/t/good-error-messages/105523/6 "2023-10-28T22:39:48Z")

</div>

I think the composable way it can work is by calling the `show` methods for the arguments involved in the `showerror` method for the error, rather than interpolating into a string as is commonly done, which is divorced from the io context and relies on the `string` method. Then, if an object supports a reasonable printing vía `show`, the error can use the that. ArgCheck.jl does this in it’s macros IIRC (though you don’t need a macro to do so).
