# Should a macro throw an error, or return expression that throws an error?

**URL:** <https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720>\
**Category:** General Usage\
**Tags:** macros\
**Created:** [January 9, 2023, 4:20pm UTC](https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720 "2023-01-09T16:20:56Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![bbejanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bbejanov/32/31047_2.png) [@bbejanov](https://discourse.julialang.org/u/bbejanov)\
**Post date:** [January 9, 2023, 4:20pm UTC](https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720/1 "2023-01-09T16:20:56Z")

</div>

I have a macro that in some circumstances must throw an error. Is there a recommended way of doing that?

For example, I can throw the error directly from the macro, or return code that throws the error.

```julia
macro A()
    if true
        error("Error message")
    else
        return :(1 + 1)
    end
end

macro B()
    if true
        return quote
            error("Error message")
        end
    else
        return :(1 + 1)
    end
end

```

If I understand it correctly, macro `@A` would cause an error during compile time, while macro `@B` would cause an error during run time. I don’t think this would make any difference to the user who calls my macro in their code. However, it makes a difference for me in my unit tests. In particular, I can do

```julia
julia> @test_throws ErrorException @B
Test Passed
  Expression: #= REPL[5]:1 =# @B
      Thrown: ErrorException

```

But I cannot test `@A` the same way, because it doesn’t even compile

```julia
julia> @test_throws ErrorException @A
ERROR: Error message
Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:33
  [2] var"@A"( __source__ ::LineNumberNode, __module__ ::Module)
      . . .

```

I’m hoping to have discussion about this. Would you recommend one versus the other and why? Am I thinking about this correctly? Are there other considerations that I should take into account?

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [January 9, 2023, 4:41pm UTC](https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720/2 "2023-01-09T16:41:22Z")

</div>

I think that you have actually answered yourself:

> [@bbejanov](#):
>
> If I understand it correctly, macro `@A` would cause an error during compile time, while macro `@B` would cause an error during run time.

That does make a difference for users too. Let’s imagine that the macro is not used interactively or in global scope, but inside a function. Then `@A` would throw the error in the moment of defining the function (it does not even need to be compiled), but `@B` would let the function exist, which would fail in the moment of calling it.

You have to decide if you need one thing or the other.

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [January 9, 2023, 4:53pm UTC](https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720/3 "2023-01-09T16:53:35Z")

</div>

> [@bbejanov](#):
>
> But I cannot test `@A` the same way, because it doesn’t even compile

Use

```julia
@test_throws LoadError @eval @A

```

but I think that only allows to capture `LoadErrors`.

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [January 9, 2023, 5:00pm UTC](https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720/4 "2023-01-09T17:00:04Z")

</div>

```julia
julia> macro errormacro(ex)
         throw(ArgumentError("wrong argument"))
       end
@errormacro (macro with 1 method)

julia> Test.@test_throws ArgumentError @macroexpand @errormacro 2
Test Passed
      Thrown: ArgumentError

```

Tiny caveat: Works only from Julia 1.7 on  
From the docstring of `LoadError`:

> LoadErrors are no longer emitted by @macroexpand, @macroexpand1, and macroexpand as of Julia 1.7.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [January 9, 2023, 5:00pm UTC](https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720/5 "2023-01-09T17:00:23Z")

</div>

If the error can be thrown at compile-time, I’d say it’s best to fail during macro expansion. Examples of early macro expansion failure include the `Test` macros themselves:

```julia
julia> using Test

julia> @macroexpand @test true unsupported_kwarg=nothing
ERROR: invalid test macro call: @test true unsupported_kwarg = nothing

```

This example also illustrates how `@macroexpand` allows to clearly separate the macro expansion stage from the runtime, which allows testing for errors that happen during macro expansion:

```julia
julia> macro A()
           error("ko")
       end
@A (macro with 1 method)

julia> @test_throws ErrorException @macroexpand @A
Test Passed
      Thrown: ErrorException

```

---

<div class="post-metadata">

**Author:** ![bbejanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bbejanov/32/31047_2.png) [@bbejanov](https://discourse.julialang.org/u/bbejanov)\
**Post date:** [January 10, 2023, 2:55pm UTC](https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720/6 "2023-01-10T14:55:49Z")

</div>

Thanks everyone for your replies and ideas. I learned about using `@macroexpand` for this test and this is very helpful, thanks again!

Btw, I tested it and it doesn’t work in Julia 1.6, but it works great in 1.7 and 1.8.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [January 10, 2023, 3:55pm UTC](https://discourse.julialang.org/t/should-a-macro-throw-an-error-or-return-expression-that-throws-an-error/92720/7 "2023-01-10T15:55:03Z")

</div>

Another way of thinking about it is that macros are basically syntax transformations. So it makes sense to throw errors as soon as possible (like syntax errors)
