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> 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> macro A()
error("ko")
end
@A (macro with 1 method)
julia> @test_throws ErrorException @macroexpand @A
Test Passed
Thrown: ErrorException