# Rethrow error from @async in macro

**URL:** <https://discourse.julialang.org/t/rethrow-error-from-async-in-macro/73244>\
**Category:** General Usage\
**Tags:** question, macros, metaprogramming\
**Created:** [December 17, 2021, 6:36am UTC](https://discourse.julialang.org/t/rethrow-error-from-async-in-macro/73244 "2021-12-17T06:36:04Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![tbenst](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbenst/32/3029_2.png) [@tbenst](https://discourse.julialang.org/u/tbenst)\
**Post date:** [December 17, 2021, 6:36am UTC](https://discourse.julialang.org/t/rethrow-error-from-async-in-macro/73244/1 "2021-12-17T06:36:04Z")

</div>

I can’t figure out how to properly rethrow an error when using a macro + @async.

This is related to [Rethrow error from @async](https://discourse.julialang.org/t/rethrow-error-from-async/48609) and [How to get backtrace of `@async` Task - #2 by pfitzseb](https://discourse.julialang.org/t/how-to-get-backtrace-of-async-task/18170/2)

```julia
import Base.Threads: @spawn

macro async_showerr(ex)
    quote
        @async try
            eval(esc(ex))
        catch err
            rethrow()
        end
    end
end

function bad_func2(i)
    try
        error("error from bad_func2")
    catch err
        rethrow()
    end
end

function bad_func(i)
    error("error from bad_func")
end

function main()
    is = collect(1:3)
    while true
        println("looping")
        @sync for i in is
            # @async bad_func(i) # shows error & halts
            # @async bad_func2(i) # shows error & halts
            @async_showerr bad_func(i) # no error, causes infinite loop. Why?
        end
        sleep(0.5)
    end
end

main()

```

Any ideas how to throw the error & halt?

---

<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:** [December 18, 2021, 5:07pm UTC](https://discourse.julialang.org/t/rethrow-error-from-async-in-macro/73244/2 "2021-12-18T17:07:39Z")

</div>

Your macro is wrong, `ex` is not used at all.

```julia
macro async_showerr(ex)
    quote
        @async try
            eval(esc(ex))
        catch err
            rethrow()
        end
    end
end

```

I think the macro has hygiene problem. `@sync` will create a local channel named `sync` and `@async` will push task to this local channel. This relies on the escaped symbol `sync` (otherwise, they may refer to different variable with the same name). However, your macro `async_showerr` pollutes the scope and cause the mismatch of these two symbols. We can check this by calling `@code_lowered main()`:

```julia
julia> @code_lowered main()
CodeInfo(
1 ─ %1 = 1:3
└── is = Main.collect(%1)
2 ┄ goto #9 if not true
3 ─ Main.println("looping")
│ %5 = Base.Channel(Base.Inf)
│ Core.NewvarNode(:(v))
│ sync#41 = %5
│ %8 = is
│ @_3 = Base.iterate(%8)
│ %10 = @_3 === nothing
│ %11 = Base.not_int(%10)
└── goto #8 if not %11
4 ┄ %13 = @_3
│ i = Core.getfield(%13, 1)
│ %15 = Core.getfield(%13, 2)
│ #1 = %new(Main.:(var"#1#2"))
│ %17 = #1
│ task = Base.Task(%17)
└── goto #6 if not false
5 ─ Base.put!(Main.:(var"##sync#41"), task)
6 ┄ Base.schedule(task)
│ task
│ @_3 = Base.iterate(%8, %15)
│ %24 = @_3 === nothing
│ %25 = Base.not_int(%24)
└── goto #8 if not %25
7 ─ goto #4
8 ┄ v = nothing
│ Base.sync_end(sync#41)
│ v
│ Main.sleep(0.5)
└── goto #2
9 ─ return nothing
)

```

So you can see two symbols `sync#41` and `Main.:(var"##sync#41")`. One is local and the other refers to a symbol in Main. So Julia will not ever synchronize at all.

To solve this problem, we need to escape the whole quote expression and everything is fine:

```julia
macro async_showerr(ex)
    esc(quote
        @async try
            eval($ex)
        catch err
            rethrow()
        end
    end)
end

```

And we get:

```julia
julia> main()
looping
ERROR: TaskFailedException

    nested task error: error from bad_func
    Stacktrace:
     [1] error(s::String)
       @ Base ./error.jl:33
     [2] bad_func(i::Int64)
       @ Main ./REPL[18]:2
     [3] (::var"#5#6"{Int64})()
       @ Main ./task.jl:411

...and 2 more exceptions.

Stacktrace:
 [1] sync_end(c::Channel{Any})
   @ Base ./task.jl:369
 [2] macro expansion
   @ ./task.jl:388 [inlined]
 [3] main()
   @ Main ./REPL[19]:5
 [4] top-level scope
   @ REPL[20]:1

```

---

<div class="post-metadata">

**Author:** ![tbenst](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbenst/32/3029_2.png) [@tbenst](https://discourse.julialang.org/u/tbenst)\
**Post date:** [December 18, 2021, 10:01pm UTC](https://discourse.julialang.org/t/rethrow-error-from-async-in-macro/73244/3 "2021-12-18T22:01:34Z")

</div>

Wow, what a phenomenal answer!! Not only did you fix it, but showed me how to figure this out myself. Thank you so much.
