# Improving error messages for structs

**URL:** <https://discourse.julialang.org/t/improving-error-messages-for-structs/124390>\
**Category:** General Usage\
**Tags:** struct, error-message\
**Created:** [January 2, 2025, 11:24pm UTC](https://discourse.julialang.org/t/improving-error-messages-for-structs/124390 "2025-01-02T23:24:13Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ken\_Williams](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ken_williams/32/5289_2.png) [@Ken\_Williams](https://discourse.julialang.org/u/Ken_Williams)\
**Post date:** [January 2, 2025, 11:24pm UTC](https://discourse.julialang.org/t/improving-error-messages-for-structs/124390/1 "2025-01-02T23:24:13Z")

</div>

If I have a situation like the following:

```julia
struct Bar
    x::Float64
    y::Float64
end

Bar(missing, 2)

```

then the error message doesn’t seem to indicate whether `x` or `y` was the problem:

```julia
ERROR: LoadError: MethodError: Cannot `convert` an object of type Missing to an object of type Float64

```

Similarly, if I’m using `Parameters.jl` for keyword constructors and/or assertions, the error is slightly worse (still doesn’t tell me the field name, and also talks about boolean stuff that confuses the caller):

```julia
using Parameters

@with_kw struct Foo
    x::Float64
    @assert 0 <= x <= 1
end

Foo(; x = missing)

```

```julia
ERROR: LoadError: TypeError: non-boolean (Missing) used in boolean context

```

I can get back to the `convert`-style error by using an inner constructor to delay the assertion:

```julia
@with_kw struct Foo
    x::Float64
    function Foo(args...)
        f = new(args...)
        @assert 0 <= f.x <= 1
    end
end

Foo(; x = missing)

```

```julia
ERROR: LoadError: MethodError: Cannot `convert` an object of type Missing to an object of type Float64

```

but that’s still not ideal.

What best practices have people come up with for giving helpful error messages when constructing composite types? Anything that plays especially well with `Parameters.jl`?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 3, 2025, 12:32am UTC](https://discourse.julialang.org/t/improving-error-messages-for-structs/124390/2 "2025-01-03T00:32:21Z")

</div>

I don’t normally find this to be a problem from other clues, but the issue is that the error isn’t coming from the context of the type constructor that can know what its fields are. `convert(Float64, missing)` and `missing && missing` do not know. So on some level, you need a constructor to check the inputs before `new` and throw errors specifically naming the positions and/or names. I’m not sure if that can generally be done in one place because of type parameters and various constructors changing how data is passed; for example, an inner constructor shouldn’t tell me that the 4th internal field had a wrong type after unrecognizable processing, the immediate outer constructor should tell me that my call provided a public keyword argument with a (different) wrong type. At least the errors thrown in callers would stop execution before callees can error, and `@with_kw`’s consistently named keyword arguments helps a lot in determining what the errors should say.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [January 3, 2025, 1:02am UTC](https://discourse.julialang.org/t/improving-error-messages-for-structs/124390/3 "2025-01-03T01:02:29Z")

</div>

Have you considered something like this:

```julia
struct Bar
    x::Float64
    y::Float64
    function Bar(x::Number, y::Number)
        new(x, y)
    end
end

```

In the REPL:

```julia-repl
julia> Bar(false, 7 + 0im) # conversion still works fine
Bar(0.0, 7.0)

julia> Bar(missing, 7 + 0im) # the error message is now friendlier
ERROR: MethodError: no method matching Bar(::Missing, ::Complex{Int64})
The type `Bar` exists, but no method is defined for this combination of argument types when trying to construct it.

Closest candidates are:
  Bar(::Number, ::Number)
   @ Main REPL[1]:4

```
