# Make Julia’s Error Codes Even Better Than Elm’s

**URL:** <https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409>\
**Category:** Internals & Design\
**Created:** [September 17, 2022, 4:26pm UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409 "2022-09-17T16:26:03Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 2, 2022, 1:48am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/42 "2022-10-02T01:48:17Z")

</div>

> [@Ronis\_BR](#):
>
> Any error inside a dynamics function of DifferetialEquations.jl leads to a huge text which is not relevant 99% of time

Your code example doesn’t drive the point home, because most of the extensive stacktrace is hidden via the horizontal scroll bar. A screenshot does a better job:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/d/6/d6ed346021173f1b8b151c4afbab8034b588ef60.jpeg)

This has nothing to do with error messages though. The noise comes from the stacktrace. And the reason it is so bad is because for many of the (immutable) `struct` definitions in DifferentialEquations.jl, every single field is parameterized. Most of those fields don’t get used, so they’re just set to `nothing`, which is why you see an extraordinary amount of `Nothing` types in the stacktrace. It seems a bit wasteful to me.

---

<div class="post-metadata">

**Author:** ![anon56330260](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@anon56330260](https://discourse.julialang.org/u/anon56330260)\
**Post date:** [October 2, 2022, 8:49am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/43 "2022-10-02T08:49:58Z")

</div>

I guess we need some post processing mechanisms to remove these intermediate frames from stacktraces. For example, we remove all but last one frames generated by external packages, and keep the frames in Main module and its submodules. That is, we only concern about errors caused by our codes, instead of errors caused by external packages.

---

<div class="post-metadata">

**Author:** ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)\
**Post date:** [October 2, 2022, 11:23pm UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/44 "2022-10-02T23:23:31Z")

</div>

This is exactly what AbbreviatedStackTraces.jl does. Not sure how it handles this example

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [October 3, 2022, 2:03am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/45 "2022-10-03T02:03:25Z")

</div>

For method errors, there are some basic improvements that can be had: [GitHub - tecosaur/HelpfulErrors.jl](https://github.com/tecosaur/HelpfulErrors.jl)

Stefan can correct me, but I don’t think there’s any performance impact there.

---

<div class="post-metadata">

**Author:** ![lawless-m](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lawless-m/32/30869_2.png) [@lawless-m](https://discourse.julialang.org/u/lawless-m)\
**Post date:** [October 3, 2022, 8:27am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/46 "2022-10-03T08:27:58Z")

</div>

```julia
I tried to access a Vector{Int64} at index [0] but ...

* uses “I” for the compiler, which does have a more relatable tone IMHO

```

Relatable to who? I am not a compiler nor is the machine a person, it is an “it”.

_You should never anthropomorphize computers, they hate that!_

---

<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 3, 2022, 8:33am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/47 "2022-10-03T08:33:04Z")

</div>

English is harder to understand when things are written in the passive voice. Giving the compiler a persona is admittedly a bit odd, but Elm shows it can work. It provides more room to the error-writer for explanation about what _I_ was doing when _I_ encountered a problem.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [October 4, 2022, 1:41am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/48 "2022-10-04T01:41:11Z")

</div>

Maybe the Royal We?

```julia
We attempted to access the array at index [3], but Our subjects failed to acquire it as the length of this array was only 2 at the moment at which thou requested the pursuit of the value of its field.

```

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [October 4, 2022, 9:22pm UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/49 "2022-10-04T21:22:06Z")

</div>

> [@jar1](#):
>
> English is harder to understand when things are written in the passive voice.

Then I’d suggest “You”

```julia
You requested computer to access the array at index [0]. 
Please think twice before doing silly things like this again.

```

That’s actually correct, the problem is usually sitting in front of the computer.

OK, now seriously - first and foremost the error messages must correctly describe what happened.

```julia
I tried to access a Vector{Int64} at index [0]

```

is plainly wrong IMO - “trying” assumes a free will, which neither compiler no computer possess.

---

<div class="post-metadata">

**Author:** ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)\
**Post date:** [October 27, 2022, 10:07pm UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/50 "2022-10-27T22:07:08Z")

</div>

What about `You told me to access a vector at index 0, looser ! Please RTFM.`

I like my computer to yell at me when I am clearly the error.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 12, 2022, 4:33am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/51 "2022-11-12T04:33:59Z")

</div>

> [@StefanKarpinski](#):
>
> Yes, that is a much better error message. Unfortunately it also tends to make functions much slower even when errors aren’t thrown because it creates a complex branch that captures all values that are used in the error message, which forces those values to be materialized and/or heap allocated. Using a static error message, on the other hand, has negligible performance impact, which is why so many error messages are like that. We have some newish technology to improve this, such as LazyString, but while that can help, it doesn’t entirely eliminate the problem. I’m planning on trying to make some better error messages like you suggest to see how bad the impact is and evaluate what kind of compiler magic we need to make it not affect performance unbearably, but it almost certainly will require some compiler work.

Does this really require compiler work? We already have `@noinline` which is sufficient for this as far as I’m aware:

```julia
my_sqrt(x::Real) = x >= 0.0 ? sqrt(x) : my_sqrt_error(x);

@noinline my_sqrt_error(x) = throw(DomainError("my_sqrt requires inputs greater than 0, you gave $x which is less than 0"));

```

```julia
julia> @benchmark my_sqrt(x) setup=(x= 100*rand())
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 2.159 ns … 20.240 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 2.160 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 2.168 ns ± 0.192 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

   █ ▁                                               
  ▂█▁▁▁▁▁▁▁▁▁▂█▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁▂▃ ▂
  2.16 ns Histogram: frequency by time 2.21 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark sqrt(x) setup=(x= 100*rand())
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 2.159 ns … 11.370 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 2.160 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 2.167 ns ± 0.107 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

   █ ▆ ▁ ▃ ▁
  ██▁▁▁▁▁▁▁▁▁▆█▁▁▁▁▁▁▁▁▁▁▃▁▁▁▁▁▁▁▁▁▁▁▄▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▄█ █
  2.16 ns Histogram: log(frequency) by time 2.21 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

In fact, now that I look, it appears that whoever wrote the `sqrt(::Float64)` method in Base already knew and took advantage of this:

```julia
julia> @code_typed sqrt(1.0)
CodeInfo(
1 ─ %1 = Base.lt_float(x, 0.0)::Bool
└── goto #3 if not %1
2 ─ invoke Base.Math.throw_complex_domainerror(:sqrt::Symbol, x::Float64)::Union{}
└── unreachable
3 ─ %5 = Base.Math.sqrt_llvm(x)::Float64
└── return %5
) => Float64

```

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [November 12, 2022, 2:54pm UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/52 "2022-11-12T14:54:23Z")

</div>

> [@Mason](#):
>
> Does this really require compiler work? We already have `@noinline` which is sufficient for this as far as I’m aware

I really don’t want to have to create a separate function for every single error.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [November 12, 2022, 3:06pm UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/53 "2022-11-12T15:06:52Z")

</div>

I mostly have `@noinline` errors in packages, and its not that awful? Also more straight forward and immediately actionable than compiler magic.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 14, 2022, 8:23pm UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/54 "2022-11-14T20:23:12Z")

</div>

> [@StefanKarpinski](#):
>
> I really don’t want to have to create a separate function for every single error.

Then a simple macro would do the trick:

```julia
macro noinline_block(args...)
    captures = esc.(args[1:end-1])
    body = esc(args[end])
    quote
        @noinline block($(captures...),) = $body
        block($(captures...),)
    end
end

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

```

```julia
julia> code_llvm(f, (Float64,), debuginfo=:none)
define double @julia_f_936(double %0) #0 {
top:
  %1 = fcmp ult double %0, 0.000000e+00
  br i1 %1, label %L5, label %L3

L3: ; preds = %top
  %2 = fadd double %0, 1.000000e+00
  ret double %2

L5: ; preds = %top
  %3 = call nonnull {}* @"j_#54#block_938"(double %0) #0
  call void @llvm.trap()
  unreachable
}

```

We could even make an `@throw` macro which automates this stuff.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [November 15, 2022, 12:56am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/55 "2022-11-15T00:56:52Z")

</div>

Great idea for `@throw`, and looks pretty slick:

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

```

Solves both the performance and boilerplate issues.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 15, 2022, 1:30am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/56 "2022-11-15T01:30:30Z")

</div>

Yeah, here’s what that macro definition would be:

```julia
macro throw(args...)
    captures = esc.(args[1:end-1])
    err = esc(args[end])
    quote
        @noinline throw_err($(captures...),) = throw($err)
        throw_err($(captures...),)
    end
end

```

Maybe this should go in a PR to base along with a spree of error message improvements?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 15, 2022, 1:47am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/58 "2022-11-15T01:47:11Z")

</div>

Nah, macro hygiene takes care of that for you:

```julia
julia> macro throw(args...)
           captures = esc.(args[1:end-1])
           err = esc(args[end])
           quote
               @noinline throw_err($(captures...),) = throw($err)
               throw_err($(captures...),)
           end
       end;

julia> @macroexpand @throw x y
quote
    #= REPL[8]:5 =#
    var"#71#throw_err"(x) = begin
            $(Expr(:meta, :noinline))
            #= REPL[8]:5 =#
            Main.throw(y)
        end
    #= REPL[8]:6 =#
    var"#71#throw_err"(x)
end

```

The `gensym` would be warranted if I `esc`’d the whole expression though. But then I’d want to interpolate `$throw` and `$Base.@inline`.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 15, 2022, 2:29am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/60 "2022-11-15T02:29:28Z")

</div>

One problem with the macro as written is that it pollutes the stacktrace. It’d be good to have a way to hide that.

```julia
julia> f(-1)
ERROR: DomainError with f requires inputs greater than 0, you gave -1 which is less than 0:

Stacktrace:
 [1] (::var"#104#throw_err#12")(x::Int64) # ⌉ 
   @ Main ./REPL[44]:5 # |<------ Yuck.
 [2] macro expansion # |
   @ ./REPL[44]:7 [inlined] # ⌋
 [3] f(x::Int64)
   @ Main ./REPL[45]:6
 [4] top-level scope
   @ REPL[46]:1

```

Does anyone know how to remove lines from the stacktrace before throwing?

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [November 16, 2022, 5:52am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/61 "2022-11-16T05:52:15Z")

</div>

You could instead do

```julia
throw(@outline DomainError(lazy"f requires inputs greater than 0, you gave $x which is less than 0"))

```

where we define

```julia
macro outline(x)
    return esc(:((() -> $x)()))
end

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 16, 2022, 6:41am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/62 "2022-11-16T06:41:31Z")

</div>

Hm, unfortunately, that seems to generate a bunch more inlined code, and is slower.

```julia
julia> macro outline(x)
           return esc(:((() -> $x)()))
       end
@outline (macro with 1 method)

julia> function f(x)
           if x >= 0
               x + 1
           else
               #throw(DomainError("f requires inputs greater than 0, you gave $x which is less than 0"))
               throw(@outline DomainError(lazy"f requires inputs greater than 0, you gave $x which is less than 0"))
           end
       end;

julia> @btime f($(Ref(1.0))[])
  2.809 ns (0 allocations: 0 bytes)
2.0

julia> code_llvm(f, Tuple{Int})
; @ REPL[24]:1 within `f`
define i64 @julia_f_624(i64 signext %0) #0 {
top:
  %gcframe16 = alloca [5 x {}*], align 16
  %gcframe16.sub = getelementptr inbounds [5 x {}*], [5 x {}*]* %gcframe16, i64 0, i64 0
  %1 = bitcast [5 x {}*]* %gcframe16 to i8*
  call void @llvm.memset.p0i8.i32(i8* noundef nonnull align 16 dereferenceable(40) %1, i8 0, i32 40, i1 false)
  %2 = getelementptr inbounds [5 x {}*], [5 x {}*]* %gcframe16, i64 0, i64 2
  %thread_ptr = call i8* asm "movq %fs:0, $0", "=r"() #6
  %ppgcstack_i8 = getelementptr i8, i8* %thread_ptr, i64 -8
  %ppgcstack = bitcast i8* %ppgcstack_i8 to {} ****
  %pgcstack = load {} ***, {}**** %ppgcstack, align 8
; @ REPL[24]:2 within `f`
; ┌ @ operators.jl:429 within `>=`
; │┌ @ int.jl:481 within `<=`
    %3 = bitcast [5 x {}*]* %gcframe16 to i64*
    store i64 12, i64* %3, align 16
    %4 = getelementptr inbounds [5 x {}*], [5 x {}*]* %gcframe16, i64 0, i64 1
    %5 = bitcast {} **%4 to {}***
    %6 = load {} **, {}*** %pgcstack, align 8
    store {} **%6, {}*** %5, align 8
    %7 = bitcast {} ***%pgcstack to {}***
    store {} **%gcframe16.sub, {}*** %7, align 8
    %8 = icmp slt i64 %0, 0
; └└
  br i1 %8, label %L5, label %L3

L3: ; preds = %top
; @ REPL[24]:3 within `f`
; ┌ @ int.jl:87 within `+`
   %9 = add nuw i64 %0, 1
   %10 = load {}*, {}** %4, align 8
   %11 = bitcast {} ***%pgcstack to {}**
   store {}* %10, {}** %11, align 8
; └
  ret i64 %9

L5: ; preds = %top
; @ REPL[24]:6 within `f`
; ┌ @ REPL[23]:2 within `#13`
; │┌ @ strings/lazy.jl:19 within `LazyString`
    %ptls_field17 = getelementptr inbounds {} **, {}*** %pgcstack, i64 2
    %12 = bitcast {} ***%ptls_field17 to i8**
    %ptls_load1819 = load i8*, i8** %12, align 8
    %13 = call noalias nonnull {}* @ijl_gc_pool_alloc(i8* %ptls_load1819, i32 1440, i32 32) #7
    %14 = bitcast {}* %13 to i64*
    %15 = getelementptr inbounds i64, i64* %14, i64 -1
    store atomic i64 139939984728400, i64* %15 unordered, align 8
    %16 = bitcast {}* %13 to {}**
    %17 = bitcast {}* %13 to <2 x {}*>*
    store <2 x {}*> zeroinitializer, <2 x {}*>* %17, align 8
    %18 = getelementptr inbounds [5 x {}*], [5 x {}*]* %gcframe16, i64 0, i64 4
    store {}* %13, {}** %18, align 16
    %ptls_load132021 = load i8*, i8** %12, align 8
    %19 = call noalias nonnull {}* @ijl_gc_pool_alloc(i8* %ptls_load132021, i32 1440, i32 32) #7
    %20 = bitcast {}* %19 to i64*
    %21 = getelementptr inbounds i64, i64* %20, i64 -1
    store atomic i64 139939991032544, i64* %21 unordered, align 8
    %22 = bitcast {}* %19 to { {}*, i64, {}* }*
    %.repack = bitcast {}* %19 to {}**
    store {}* inttoptr (i64 139940196512528 to {}*), {}** %.repack, align 8
    %.repack6 = getelementptr inbounds { {}*, i64, {}* }, { {}*, i64, {}* }* %22, i64 0, i32 1
    store i64 %0, i64* %.repack6, align 8
    %.repack8 = getelementptr inbounds { {}*, i64, {}* }, { {}*, i64, {}* }* %22, i64 0, i32 2
    store {}* inttoptr (i64 139937774046432 to {}*), {}** %.repack8, align 8
    store {}* %19, {}** %16, align 8
    %23 = load atomic i64, i64* %15 unordered, align 8
    %24 = and i64 %23, 3
    %25 = icmp eq i64 %24, 3
    br i1 %25, label %26, label %27

26: ; preds = %L5
    call void @ijl_gc_queue_root({}* nonnull %13)
    br label %27

27: ; preds = %26, %L5
    %28 = bitcast {}** %2 to [2 x {}*]*
; │└
   call void @j_DomainError_626([2 x {}*]* noalias nocapture nonnull sret([2 x {}*]) %28, {}* nonnull readonly %13) #0
; └
  %ptls_load152223 = load i8*, i8** %12, align 8
  %29 = call noalias nonnull {}* @ijl_gc_pool_alloc(i8* %ptls_load152223, i32 1440, i32 32) #7
  %30 = bitcast {}* %29 to i64*
  %31 = getelementptr inbounds i64, i64* %30, i64 -1
  store atomic i64 139939981380608, i64* %31 unordered, align 8
  %32 = bitcast {}* %29 to i8*
  %33 = bitcast {}** %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(16) %32, i8* noundef nonnull align 16 dereferenceable(16) %33, i64 16, i1 false)
  call void @ijl_throw({}* %29)
  unreachable
}

```

Marking the function inside `@outline` as `@noinline` and avoiding capturing variables didn’t seem to help.

---

<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:** [November 23, 2022, 1:14am UTC](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409/63 "2022-11-23T01:14:58Z")

</div>

Python recently introduced some nice new error messages.

> In order to identify the range of source code being executed when exceptions are raised, this proposal requires adding new data for every bytecode instruction.  
> …  
> We understand that the extra cost of this information may not be acceptable for some users, so we propose an opt-out mechanism which will cause generated code objects to not have the extra information while also allowing pyc files to not include the extra information.

> **[PEP 657 – Include Fine Grained Error Locations in Tracebacks | peps.python.org](https://peps.python.org/pep-0657/)**
>
> Python Enhancement Proposals (PEPs)

[Previous page](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409.md?page=2)

[Next page](https://discourse.julialang.org/t/make-julia-s-error-codes-even-better-than-elm-s/87409.md?page=4)
