# Improving macro error messages

**URL:** <https://forum.crystal-lang.org/t/improving-macro-error-messages/2811>\
**Category:** Community\
**Created:** [December 22, 2020, 11:02pm UTC](https://forum.crystal-lang.org/t/improving-macro-error-messages/2811 "2020-12-22T23:02:10Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![BrucePerens](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bruceperens/32/852_2.png) [@BrucePerens](https://forum.crystal-lang.org/u/BrucePerens)\
**Post date:** [December 22, 2020, 11:02pm UTC](https://forum.crystal-lang.org/t/improving-macro-error-messages/2811/1 "2020-12-22T23:02:10Z")

</div>

One of the big difficulties for Crystal users, IMO, is that macro error messages are often incomprehensible. I recently came up with a means of giving users a bit more clue, which is shown in the error report from --error-trace and does not add space in the compiled code. Here is some sample macro code to demonstrate what I’m doing:

```crystal
macro delegate2(name, to, file = __FILE__ , line = __LINE__ )
# This method was generated through an invocation of
# `{{@type.name}}.delegate2 {{name}}, to: {{to}}`
# at {{file.id}}:{{line.id}}.

```

When I test the code with a deliberately-injected error, I get this output from `crystal build --error-trace` . _Every_ ASTNode, and thus every macro argument, includes `ASTNode#filename` and `ASTNode#line_number` , you don’t have to pass **FILE** and **LINE**.

```auto
There was a problem expanding macro 'delegate2'

Called macro defined in delegate.cr:2:3

 2 | macro delegate2(name, to, file = __FILE__ , line = __LINE__ )

Which expanded to:

 > 1 |    
 ... (blank lines)
 > 31 |        
 > 32 | # This method was generated through an invocation of
 > 33 | # `A.delegate2 inspect, to: @a`
 > 34 | # at /home/bruce/Crystal/delegate/src/delegate.cr:46.
 > 35 | # The target method is at
 > 36 | # /usr/share/crystal/src/reference.cr:71
 > 37 | def inspect(io : IO) : Nil 
 > 38 | @a.inspect(io) 
 > 39 | @a.foobar
 > 40 | end
 > 41 |        
... (blank lines)
 > 74 |        
 > 75 | # This method was generated through an invocation of
 > 76 | # `A.delegate2 inspect, to: @a`
 > 77 | # at /home/bruce/Crystal/delegate/src/delegate.cr:46.
 > 78 | # The target method is at
 > 79 | # /usr/share/crystal/src/object.cr:155
 > 80 | def inspect(io : IO) : Nil 
 > 81 | @a.inspect(io) 
 > 82 | @a.foobar
 > 83 | end
 > 84 |        
... (blank lines)
 > 93 |        
 > 94 | # This method was generated through an invocation of
 > 95 | # `A.delegate2 inspect, to: @a`
 > 96 | # at /home/bruce/Crystal/delegate/src/delegate.cr:46.
 > 97 | # The target method is at
 > 98 | # /usr/share/crystal/src/object.cr:143
 > 99 | def inspect() : String 
 > 100 | @a.inspect() 
 > 101 | @a.foobar
 > 102 | end

```

The progam containing this is at [https://github.com/BrucePerens/delegate](https://github.com/BrucePerens/delegate)

Now, while comments work, especially with error trace on, we could improve on this:

1. Assign an annotation that will be output when there is an error in a macro, even without --error-trace. Macro developers could put information about the macro arguments in it.
2. Just print the filename and line number of all macro arguments in macro error messages.
