Sija/raven.cr

Issue capturing Stripe errors using raven.cr

Closed this issue ยท 8 comments

Hey @Sija,

First of all, I want to offer my thanks for all of your contributions to the ecosystem. The way you communicate in GitHub issues is always super friendly and thorough, which I know is a challenge when you've got as many repos as you do going!

I'm not 100% sure why this issue is occurring yet, and if there's not enough here for you to know either then you can say so and I'll go bang my head against the wall a bit more ๐Ÿ˜„ .

I'm using the raven.cr shard (thank you!) to track errors in my Lucky Framework app. In that app, I'm also using the stripe.cr shard for payments. stripe.cr has a custom error that's serializable, and as of Crystal 0.36.1 the compiler is complaining with the following message:

web          | In lib/any_hash/src/any_hash.cr:74:7
web          | 
web          |  74 | value.as(V)
web          |       ^
web          | Error: can't cast JSON::PullParser to AnyHash::JSONTypes::Value

Best I can tell from a build command with --error-trace, this is coming from an issue where the custom (JSON::Serializable) Stripe::Error in stripe.cr can't be parsed by raven.cr when an exception is raised.

stripe.cr extends Exception to support JSON::Serializable:

class Exception
  @[JSON::Field(ignore: true)]
  @cause : Exception?

  @[JSON::Field(ignore: true)]
  @callstack : Exception::CallStack?
end

Then defines a Stripe::Error that I think is causing the issue:

class Stripe::Error < Exception
  include JSON::Serializable

  enum Type
    ApiConnectionError
    ApiError
    AuthenticationError
    CardError
    IdempotencyError
    InvalidRequestError
    RateLimitError
  end

  @[JSON::Field(converter: Enum::StringConverter(Stripe::Error::Type))]
  property type : Stripe::Error::Type
  property charge : String?
  property code : String?
  property decline_code : String?
  property doc_url : String?
  property message : String?
  property param : String?
end

Do you have any ideas for a PR I could submit to stripe.cr that would allow its Stripe::Error to be handled by raven.cr, or do you think I'm barking up the wrong tree, and the issue doesn't lie with either stripe.cr or any_hash.cr?

Including the full build with --error-trace here, in case it's helpful.

Click here to expand the stack trace

In src/start_server.cr:16:12

 16 | app_server.listen
                 ^-----
Error: instantiating 'AppServer#listen()'


In src/app_server.cr:27:12

 27 | server.listen
             ^-----
Error: instantiating 'HTTP::Server#listen()'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server.cr:468:13

 468 | spawn handle_client(_io)
       ^
Error: expanding macro


There was a problem expanding macro 'spawn'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/concurrent.cr:99:1

 99 | macro spawn(call, *, name = nil, same_thread = false, &block)

Which expanded to:

 >  1 |   
 >  2 | 
 >  3 |   
 >  4 |     ->(
 >  5 |       
 >  6 |         __arg0 : typeof(_io),
 >  7 |       
 >  8 |       
 >  9 |       ) {
 > 10 |       spawn(name: nil, same_thread: false) do
 > 11 |         handle_client(
 > 12 |           
 > 13 |             __arg0,
 > 14 |           
 > 15 |           
 > 16 |         )
 > 17 |       end
 > 18 |       }.call(
 > 19 |         
 > 20 |           _io,
 > 21 |         
 > 22 |         
 > 23 |       )
 > 24 |   
Error: instantiating 'handle_client(IO+)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server.cr:513:16

 513 | @processor.process(io, io)
                  ^------
Error: instantiating 'HTTP::Server::RequestProcessor#process(IO+, IO+)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/request_processor.cr:50:20

 50 | @handler.call(context)
               ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/compress_handler.cr:12:5

 12 | {% if flag?(:without_zlib) %}
      ^
Error: expanding macro


There was a problem expanding macro 'macro_5289581856'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/compress_handler.cr:12:5

 12 | {% if flag?(:without_zlib) %}

Which expanded to:

 > 1 | 
 > 2 |       context.response.output = CompressIO.new(context.response.output, context)
 > 3 |       call_next(context)
 > 4 |     
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/error_handler.cr:17:7

 17 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/log_handler.cr:20:7

 20 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/charms/static_file_handler.cr:5:5

 5 | super(context)
     ^----
Error: instantiating 'super(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/static_file_handler.cr:34:9

 34 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/static_file_handler.cr:34:9

 34 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/websocket_handler.cr:25:14

 25 | return call_next context
             ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/error_handler.cr:14:5

 14 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/force_ssl_handler.cr:37:7

 37 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/http_method_override_handler.cr:11:5

 11 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/log_handler.cr:28:5

 28 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/remote_ip_handler.cr:15:5

 15 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/route_handler.cr:10:52

 10 | handler.payload.new(context, handler.params).perform_action
                                                   ^-------------
Error: instantiating 'Lucky::Action+#perform_action()'


In lib/lucky/src/lucky/renderable.cr:111:16

 111 | response = call
                  ^---
Error: instantiating 'call()'


In src/actions/me/update.cr:13:7

 13 | html Me::EditPage, operation: operation, user: updated_user
    ^
Error: expanding macro


There was a problem expanding macro 'html'

Called macro defined in lib/lucky/src/lucky/renderable.cr:46:3

 46 | macro html(page_class = nil, **assigns)

Which expanded to:

 >  1 |     
 >  2 |     validate_page_class!(Me::EditPage)
 >  3 | 
 >  4 |     # Found in Me::Update
 >  5 |     view = Me::EditPage.new(
 >  6 |       context: context,
 >  7 |       
 >  8 |         operation: operation,
 >  9 |       
 > 10 |         user: updated_user,
 > 11 |       
 > 12 |       
 > 13 |         current_user: current_user,
 > 14 |       
 > 15 |     )
 > 16 |     Lucky::TextResponse.new(
 > 17 |       context,
 > 18 |       "text/html",
 > 19 |       view.perform_render,
 > 20 |       debug_message: log_message(view),
 > 21 |       enable_cookies: enable_cookies?
 > 22 |     )
 > 23 |   
Error: instantiating 'Me::EditPage#perform_render()'


In lib/lucky/src/lucky/html_builder.cr:86:5

 86 | render
      ^-----
Error: instantiating 'render()'


In src/pages/main_layout.cr:32:11

 32 | content
      ^------
Error: instantiating 'content()'


In src/pages/me/edit_page.cr:13:19

 13 | body: ->{ render_settings_page },
                ^-------------------
Error: instantiating 'render_settings_page()'


In src/pages/me/edit_page.cr:36:5

 36 | render_subscription_details
      ^--------------------------
Error: instantiating 'render_subscription_details()'


In src/pages/me/edit_page.cr:105:15

 105 | render_invoice_information(stripe_subscription)
       ^-------------------------
Error: instantiating 'render_invoice_information(Stripe::Subscription)'


In src/pages/me/edit_page.cr:131:31

 131 | invoice = Stripe::Invoice.retrieve(stripe_subscription.latest_invoice.to_s)
                                 ^-------
Error: instantiating 'Stripe::Invoice.class#retrieve(String)'


In lib/stripe/src/stripe/methods/core/invoices/retrieve_invoice.cr:8:19

 8 | raise Error.from_json(response.body, "error")
                 ^--------
Error: instantiating 'Stripe::Error.class#from_json(String, String)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/from_json.cr:27:5

 27 | new parser
      ^--
Error: instantiating 'new(JSON::PullParser)'


In lib/stripe/src/stripe/error.cr:2:3

 2 | include JSON::Serializable
     ^
Error: expanding macro


There was a problem expanding macro 'included'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/serialization.cr:133:5

 133 | macro included

Which expanded to:

 >  1 |       # Define a `new` directly in the included type,
 >  2 |       # so it overloads well with other possible initializes
 >  3 | 
 >  4 |       def self.new(pull : ::JSON::PullParser)
 >  5 |         new_from_json_pull_parser(pull)
 >  6 |       end
 >  7 | 
 >  8 |       private def self.new_from_json_pull_parser(pull : ::JSON::PullParser)
 >  9 |         instance = allocate
 > 10 |         instance.initialize(__pull_for_json_serializable: pull)
 > 11 |         GC.add_finalizer(instance) if instance.responds_to?(:finalize)
 > 12 |         instance
 > 13 |       end
 > 14 | 
 > 15 |       # When the type is inherited, carry over the `new`
 > 16 |       # so it can compete with other possible initializes
 > 17 | 
 > 18 |       macro inherited
 > 19 |         def self.new(pull : ::JSON::PullParser)
 > 20 |           new_from_json_pull_parser(pull)
 > 21 |         end
 > 22 |       end
 > 23 |     
Error: instantiating 'new_from_json_pull_parser(JSON::PullParser)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/serialization.cr:159:7

 159 | {% begin %}
       ^
Error: expanding macro


There was a problem expanding macro 'macro_5552992704'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/serialization.cr:159:7

 159 | {% begin %}

Which expanded to:

 >   1 | 
 >   2 |         
 >   3 |         
 >   4 |           
 >   5 |           
 >   6 |             
 >   7 |           
 >   8 |         
 >   9 |           
 >  10 |           
 >  11 |         
 >  12 |           
 >  13 |           
 >  14 |         
 >  15 |           
 >  16 |           
 >  17 |             
 >  18 |           
 >  19 |         
 >  20 |           
 >  21 |           
 >  22 |             
 >  23 |           
 >  24 |         
 >  25 |           
 >  26 |           
 >  27 |             
 >  28 |           
 >  29 |         
 >  30 |           
 >  31 |           
 >  32 |             
 >  33 |           
 >  34 |         
 >  35 |           
 >  36 |           
 >  37 |             
 >  38 |           
 >  39 |         
 >  40 |           
 >  41 |           
 >  42 |             
 >  43 |           
 >  44 |         
 >  45 |           
 >  46 |           
 >  47 |             
 >  48 |           
 >  49 |         
 >  50 |           
 >  51 |           
 >  52 |             
 >  53 |           
 >  54 |         
 >  55 |           
 >  56 |           
 >  57 |             
 >  58 |           
 >  59 |         
 >  60 |           
 >  61 |           
 >  62 |             
 >  63 |           
 >  64 |         
 >  65 | 
 >  66 |         
 >  67 |           __temp_9380 = nil
 >  68 |           __temp_9381 = false
 >  69 |         
 >  70 |           __temp_9382 = nil
 >  71 |           __temp_9383 = false
 >  72 |         
 >  73 |           __temp_9384 = nil
 >  74 |           __temp_9385 = false
 >  75 |         
 >  76 |           __temp_9386 = nil
 >  77 |           __temp_9387 = false
 >  78 |         
 >  79 |           __temp_9388 = nil
 >  80 |           __temp_9389 = false
 >  81 |         
 >  82 |           __temp_9390 = nil
 >  83 |           __temp_9391 = false
 >  84 |         
 >  85 |           __temp_9392 = nil
 >  86 |           __temp_9393 = false
 >  87 |         
 >  88 |           __temp_9394 = nil
 >  89 |           __temp_9395 = false
 >  90 |         
 >  91 |           __temp_9396 = nil
 >  92 |           __temp_9397 = false
 >  93 |         
 >  94 |           __temp_9398 = nil
 >  95 |           __temp_9399 = false
 >  96 |         
 >  97 |           __temp_9400 = nil
 >  98 |           __temp_9401 = false
 >  99 |         
 > 100 | 
 > 101 |         __temp_9402 = pull.location
 > 102 |         begin
 > 103 |           pull.read_begin_object
 > 104 |         rescue exc : ::JSON::ParseException
 > 105 |           raise ::JSON::SerializableError.new(exc.message, self.class.to_s, nil, *__temp_9402, exc)
 > 106 |         end
 > 107 |         until pull.kind.end_object?
 > 108 |           __temp_9403 = pull.location
 > 109 |           key = pull.read_object_key
 > 110 |           case key
 > 111 |           
 > 112 |             when "message"
 > 113 |               __temp_9381 = true
 > 114 |               begin
 > 115 |                 __temp_9380 =
 > 116 |                    pull.read_null_or { 
 > 117 | 
 > 118 |                   
 > 119 | 
 > 120 |                   
 > 121 |                     ::Union((String | Nil)).new(pull)
 > 122 |                   
 > 123 | 
 > 124 |                   
 > 125 | 
 > 126 |                  } 
 > 127 |               rescue exc : ::JSON::ParseException
 > 128 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "message", *__temp_9403, exc)
 > 129 |               end
 > 130 |           
 > 131 |             when "__raven_event_id"
 > 132 |               __temp_9383 = true
 > 133 |               begin
 > 134 |                 __temp_9382 =
 > 135 |                    pull.read_null_or { 
 > 136 | 
 > 137 |                   
 > 138 | 
 > 139 |                   
 > 140 |                     ::Union((String | Nil)).new(pull)
 > 141 |                   
 > 142 | 
 > 143 |                   
 > 144 | 
 > 145 |                  } 
 > 146 |               rescue exc : ::JSON::ParseException
 > 147 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "__raven_event_id", *__temp_9403, exc)
 > 148 |               end
 > 149 |           
 > 150 |             when "__raven_user"
 > 151 |               __temp_9385 = true
 > 152 |               begin
 > 153 |                 __temp_9384 =
 > 154 |                    pull.read_null_or { 
 > 155 | 
 > 156 |                   
 > 157 | 
 > 158 |                   
 > 159 |                     ::Union((AnyHash::JSON | Nil)).new(pull)
 > 160 |                   
 > 161 | 
 > 162 |                   
 > 163 | 
 > 164 |                  } 
 > 165 |               rescue exc : ::JSON::ParseException
 > 166 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "__raven_user", *__temp_9403, exc)
 > 167 |               end
 > 168 |           
 > 169 |             when "__raven_tags"
 > 170 |               __temp_9387 = true
 > 171 |               begin
 > 172 |                 __temp_9386 =
 > 173 |                    pull.read_null_or { 
 > 174 | 
 > 175 |                   
 > 176 | 
 > 177 |                   
 > 178 |                     ::Union((AnyHash::JSON | Nil)).new(pull)
 > 179 |                   
 > 180 | 
 > 181 |                   
 > 182 | 
 > 183 |                  } 
 > 184 |               rescue exc : ::JSON::ParseException
 > 185 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "__raven_tags", *__temp_9403, exc)
 > 186 |               end
 > 187 |           
 > 188 |             when "__raven_extra"
 > 189 |               __temp_9389 = true
 > 190 |               begin
 > 191 |                 __temp_9388 =
 > 192 |                    pull.read_null_or { 
 > 193 | 
 > 194 |                   
 > 195 | 
 > 196 |                   
 > 197 |                     ::Union((AnyHash::JSON | Nil)).new(pull)
 > 198 |                   
 > 199 | 
 > 200 |                   
 > 201 | 
 > 202 |                  } 
 > 203 |               rescue exc : ::JSON::ParseException
 > 204 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "__raven_extra", *__temp_9403, exc)
 > 205 |               end
 > 206 |           
 > 207 |             when "type"
 > 208 |               __temp_9391 = true
 > 209 |               begin
 > 210 |                 __temp_9390 =
 > 211 |                   
 > 212 | 
 > 213 |                   
 > 214 | 
 > 215 |                   
 > 216 |                     Enum::StringConverter(Stripe::Error::Type).from_json(pull)
 > 217 |                   
 > 218 | 
 > 219 |                   
 > 220 | 
 > 221 |                 
 > 222 |               rescue exc : ::JSON::ParseException
 > 223 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "type", *__temp_9403, exc)
 > 224 |               end
 > 225 |           
 > 226 |             when "charge"
 > 227 |               __temp_9393 = true
 > 228 |               begin
 > 229 |                 __temp_9392 =
 > 230 |                    pull.read_null_or { 
 > 231 | 
 > 232 |                   
 > 233 | 
 > 234 |                   
 > 235 |                     ::Union((String | Nil)).new(pull)
 > 236 |                   
 > 237 | 
 > 238 |                   
 > 239 | 
 > 240 |                  } 
 > 241 |               rescue exc : ::JSON::ParseException
 > 242 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "charge", *__temp_9403, exc)
 > 243 |               end
 > 244 |           
 > 245 |             when "code"
 > 246 |               __temp_9395 = true
 > 247 |               begin
 > 248 |                 __temp_9394 =
 > 249 |                    pull.read_null_or { 
 > 250 | 
 > 251 |                   
 > 252 | 
 > 253 |                   
 > 254 |                     ::Union((String | Nil)).new(pull)
 > 255 |                   
 > 256 | 
 > 257 |                   
 > 258 | 
 > 259 |                  } 
 > 260 |               rescue exc : ::JSON::ParseException
 > 261 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "code", *__temp_9403, exc)
 > 262 |               end
 > 263 |           
 > 264 |             when "decline_code"
 > 265 |               __temp_9397 = true
 > 266 |               begin
 > 267 |                 __temp_9396 =
 > 268 |                    pull.read_null_or { 
 > 269 | 
 > 270 |                   
 > 271 | 
 > 272 |                   
 > 273 |                     ::Union((String | Nil)).new(pull)
 > 274 |                   
 > 275 | 
 > 276 |                   
 > 277 | 
 > 278 |                  } 
 > 279 |               rescue exc : ::JSON::ParseException
 > 280 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "decline_code", *__temp_9403, exc)
 > 281 |               end
 > 282 |           
 > 283 |             when "doc_url"
 > 284 |               __temp_9399 = true
 > 285 |               begin
 > 286 |                 __temp_9398 =
 > 287 |                    pull.read_null_or { 
 > 288 | 
 > 289 |                   
 > 290 | 
 > 291 |                   
 > 292 |                     ::Union((String | Nil)).new(pull)
 > 293 |                   
 > 294 | 
 > 295 |                   
 > 296 | 
 > 297 |                  } 
 > 298 |               rescue exc : ::JSON::ParseException
 > 299 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "doc_url", *__temp_9403, exc)
 > 300 |               end
 > 301 |           
 > 302 |             when "param"
 > 303 |               __temp_9401 = true
 > 304 |               begin
 > 305 |                 __temp_9400 =
 > 306 |                    pull.read_null_or { 
 > 307 | 
 > 308 |                   
 > 309 | 
 > 310 |                   
 > 311 |                     ::Union((String | Nil)).new(pull)
 > 312 |                   
 > 313 | 
 > 314 |                   
 > 315 | 
 > 316 |                  } 
 > 317 |               rescue exc : ::JSON::ParseException
 > 318 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "param", *__temp_9403, exc)
 > 319 |               end
 > 320 |           
 > 321 |           else
 > 322 |             on_unknown_json_attribute(pull, key, __temp_9403)
 > 323 |           end
 > 324 |         end
 > 325 |         pull.read_next
 > 326 | 
 > 327 |         
 > 328 |           
 > 329 | 
 > 330 |           
 > 331 |             
 > 332 |               @message = __temp_9381 ? __temp_9380 : nil
 > 333 |             
 > 334 |           
 > 335 | 
 > 336 |           
 > 337 |         
 > 338 |           
 > 339 | 
 > 340 |           
 > 341 |             
 > 342 |               @__raven_event_id = __temp_9383 ? __temp_9382 : nil
 > 343 |             
 > 344 |           
 > 345 | 
 > 346 |           
 > 347 |         
 > 348 |           
 > 349 | 
 > 350 |           
 > 351 |             
 > 352 |               @__raven_user = __temp_9385 ? __temp_9384 : nil
 > 353 |             
 > 354 |           
 > 355 | 
 > 356 |           
 > 357 |         
 > 358 |           
 > 359 | 
 > 360 |           
 > 361 |             
 > 362 |               @__raven_tags = __temp_9387 ? __temp_9386 : nil
 > 363 |             
 > 364 |           
 > 365 | 
 > 366 |           
 > 367 |         
 > 368 |           
 > 369 | 
 > 370 |           
 > 371 |             
 > 372 |               @__raven_extra = __temp_9389 ? __temp_9388 : nil
 > 373 |             
 > 374 |           
 > 375 | 
 > 376 |           
 > 377 |         
 > 378 |           
 > 379 |             if __temp_9390.nil? && !__temp_9391 && !::Union(Stripe::Error::Type).nilable?
 > 380 |               raise ::JSON::SerializableError.new("Missing JSON attribute: type", self.class.to_s, nil, *__temp_9402, nil)
 > 381 |             end
 > 382 |           
 > 383 | 
 > 384 |           
 > 385 |             @type = (__temp_9390).as(Stripe::Error::Type)
 > 386 |           
 > 387 | 
 > 388 |           
 > 389 |         
 > 390 |           
 > 391 | 
 > 392 |           
 > 393 |             
 > 394 |               @charge = __temp_9393 ? __temp_9392 : nil
 > 395 |             
 > 396 |           
 > 397 | 
 > 398 |           
 > 399 |         
 > 400 |           
 > 401 | 
 > 402 |           
 > 403 |             
 > 404 |               @code = __temp_9395 ? __temp_9394 : nil
 > 405 |             
 > 406 |           
 > 407 | 
 > 408 |           
 > 409 |         
 > 410 |           
 > 411 | 
 > 412 |           
 > 413 |             
 > 414 |               @decline_code = __temp_9397 ? __temp_9396 : nil
 > 415 |             
 > 416 |           
 > 417 | 
 > 418 |           
 > 419 |         
 > 420 |           
 > 421 | 
 > 422 |           
 > 423 |             
 > 424 |               @doc_url = __temp_9399 ? __temp_9398 : nil
 > 425 |             
 > 426 |           
 > 427 | 
 > 428 |           
 > 429 |         
 > 430 |           
 > 431 | 
 > 432 |           
 > 433 |             
 > 434 |               @param = __temp_9401 ? __temp_9400 : nil
 > 435 |             
 > 436 |           
 > 437 | 
 > 438 |           
 > 439 |         
 > 440 |       
Error: instantiating '(AnyHash::JSON | Nil).class#new(JSON::PullParser)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/from_json.cr:291:3

 291 | {% begin %}
       ^
Error: expanding macro


There was a problem expanding macro 'macro_5553451120'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/from_json.cr:291:3

 291 | {% begin %}

Which expanded to:

 >  1 | 
 >  2 |     
 >  3 |     
 >  4 | 
 >  5 |     # If after traversing all the types we are left with just one
 >  6 |     # non-primitive type, we can parse it directly (no need to use `read_raw`)
 >  7 |     
 >  8 |       return AnyHash::JSON.new(pull)
 >  9 |     
 > 10 |   
Error: instantiating 'AnyHash::JSON.class#new(JSON::PullParser)'


In lib/any_hash/src/any_hash.cr:146:30

 146 | @__hash__ = self.class.deep_cast_value(hash).as(Hash(K, V))
                              ^--------------
Error: instantiating 'AnyHash::JSON.class#deep_cast_value(JSON::PullParser)'


In lib/any_hash/src/any_hash.cr:74:7

 74 | value.as(V)
      ^
Error: can't cast JSON::PullParser to AnyHash::JSONTypes::Value

Sija commented

Hi @stephendolan,

First of all thank you for your kind words โค๏ธ I'm happy you're finding my contributions useful :)
As for the root cause of your issue I believe it's related to the include JSON::Serializable part within the Exception descendent class - Stripe::Error. raven.cr extends Exception class with several properties which are not serializable, see https://github.com/Sija/raven.cr/blob/00e1f577c83095bc3321441b070a643e9be84c3e/src/raven/ext/exception.cr.

Adding @[JSON::Field(ignore: true)] to those should fix your issue, but if not I'll try to investigate further.

Do you have any ideas for a PR I could submit to stripe.cr that would allow its Stripe::Error to be handled by raven.cr, or do you think I'm barking up the wrong tree, and the issue doesn't lie with either stripe.cr or any_hash.cr?

I'd try adding that into your project directly:

class Exception
  @[JSON::Field(ignore: true)]
  @__raven_event_id : String?

  {% for key in %i(user tags extra) %}
    @[JSON::Field(ignore: true)]
    @__raven_{{ key.id }} : AnyHash::JSON?
  {% end %}
end

@Sija Thank you very much for responding so quickly!

I've added that snippet to the stripe.cr Exception class, so that it now looks like this:

class Exception
  @[JSON::Field(ignore: true)]
  @__raven_event_id : String?

  {% for key in %i(user tags extra) %}
    @[JSON::Field(ignore: true)]
    @__raven_{{ key.id }} : AnyHash::JSON?
  {% end %}

  @[JSON::Field(ignore: true)]
  @cause : Exception?

  @[JSON::Field(ignore: true)]
  @callstack : Exception::CallStack?
end

Unfortunately, I'm getting the same thing from the compiler:

In lib/any_hash/src/any_hash.cr:74:7

 74 | value.as(V)
      ^
Error: can't cast JSON::PullParser to AnyHash::JSONTypes::Value

Is it possible that a solution could be to add a when JSON::PullParser item to src/any_hash.cr:58 ? I was doing some more digging last night to see if there's an easy way to simply retrieve the full JSON from a PullParser, but it seems like you have to stream the output based on the type of key, so I'm not sure how well that would really work...

I only ask because I could see this becoming an issue for other API wrapper libraries, where they want to ingest an API error and serialize it into a Crystal Exception that can be handled by raven.cr. It'd be cool to have a solution in this lib so that the raven.cr stuff doesn't have to "leak" out into other shards, and you could still extend Exception as much as you'd like here.

Here's the full stack trace! I *think* it remained the same.

In src/start_server.cr:16:12

 16 | app_server.listen
                 ^-----
Error: instantiating 'AppServer#listen()'


In src/app_server.cr:27:12

 27 | server.listen
             ^-----
Error: instantiating 'HTTP::Server#listen()'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server.cr:468:13

 468 | spawn handle_client(_io)
       ^
Error: expanding macro


There was a problem expanding macro 'spawn'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/concurrent.cr:99:1

 99 | macro spawn(call, *, name = nil, same_thread = false, &block)

Which expanded to:

 >  1 |   
 >  2 | 
 >  3 |   
 >  4 |     ->(
 >  5 |       
 >  6 |         __arg0 : typeof(_io),
 >  7 |       
 >  8 |       
 >  9 |       ) {
 > 10 |       spawn(name: nil, same_thread: false) do
 > 11 |         handle_client(
 > 12 |           
 > 13 |             __arg0,
 > 14 |           
 > 15 |           
 > 16 |         )
 > 17 |       end
 > 18 |       }.call(
 > 19 |         
 > 20 |           _io,
 > 21 |         
 > 22 |         
 > 23 |       )
 > 24 |   
Error: instantiating 'handle_client(IO+)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server.cr:513:16

 513 | @processor.process(io, io)
                  ^------
Error: instantiating 'HTTP::Server::RequestProcessor#process(IO+, IO+)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/request_processor.cr:50:20

 50 | @handler.call(context)
               ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/compress_handler.cr:12:5

 12 | {% if flag?(:without_zlib) %}
      ^
Error: expanding macro


There was a problem expanding macro 'macro_5281009664'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/compress_handler.cr:12:5

 12 | {% if flag?(:without_zlib) %}

Which expanded to:

 > 1 | 
 > 2 |       context.response.output = CompressIO.new(context.response.output, context)
 > 3 |       call_next(context)
 > 4 |     
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/error_handler.cr:17:7

 17 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/log_handler.cr:20:7

 20 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/charms/static_file_handler.cr:5:5

 5 | super(context)
     ^----
Error: instantiating 'super(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/static_file_handler.cr:34:9

 34 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/static_file_handler.cr:34:9

 34 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handlers/websocket_handler.cr:25:14

 25 | return call_next context
             ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/error_handler.cr:14:5

 14 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/force_ssl_handler.cr:37:7

 37 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/http_method_override_handler.cr:11:5

 11 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/log_handler.cr:28:5

 28 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/remote_ip_handler.cr:15:5

 15 | call_next(context)
      ^--------
Error: instantiating 'call_next(HTTP::Server::Context)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/http/server/handler.cr:28:20

 28 | next_handler.call(context)
                   ^---
Error: instantiating '(HTTP::Handler | Proc(HTTP::Server::Context, Nil))#call(HTTP::Server::Context)'


In lib/lucky/src/lucky/route_handler.cr:10:52

 10 | handler.payload.new(context, handler.params).perform_action
                                                   ^-------------
Error: instantiating 'Lucky::Action+#perform_action()'


In lib/lucky/src/lucky/renderable.cr:111:16

 111 | response = call
                  ^---
Error: instantiating 'call()'


In src/actions/me/update.cr:13:7

 13 | html Me::EditPage, operation: operation, user: updated_user
    ^
Error: expanding macro


There was a problem expanding macro 'html'

Called macro defined in lib/lucky/src/lucky/renderable.cr:46:3

 46 | macro html(page_class = nil, **assigns)

Which expanded to:

 >  1 |     
 >  2 |     validate_page_class!(Me::EditPage)
 >  3 | 
 >  4 |     # Found in Me::Update
 >  5 |     view = Me::EditPage.new(
 >  6 |       context: context,
 >  7 |       
 >  8 |         operation: operation,
 >  9 |       
 > 10 |         user: updated_user,
 > 11 |       
 > 12 |       
 > 13 |         current_user: current_user,
 > 14 |       
 > 15 |     )
 > 16 |     Lucky::TextResponse.new(
 > 17 |       context,
 > 18 |       "text/html",
 > 19 |       view.perform_render,
 > 20 |       debug_message: log_message(view),
 > 21 |       enable_cookies: enable_cookies?
 > 22 |     )
 > 23 |   
Error: instantiating 'Me::EditPage#perform_render()'


In lib/lucky/src/lucky/html_builder.cr:86:5

 86 | render
      ^-----
Error: instantiating 'render()'


In src/pages/main_layout.cr:32:11

 32 | content
      ^------
Error: instantiating 'content()'


In src/pages/me/edit_page.cr:13:19

 13 | body: ->{ render_settings_page },
                ^-------------------
Error: instantiating 'render_settings_page()'


In src/pages/me/edit_page.cr:36:5

 36 | render_subscription_details
      ^--------------------------
Error: instantiating 'render_subscription_details()'


In src/pages/me/edit_page.cr:105:15

 105 | render_invoice_information(stripe_subscription)
       ^-------------------------
Error: instantiating 'render_invoice_information(Stripe::Subscription)'


In src/pages/me/edit_page.cr:131:31

 131 | invoice = Stripe::Invoice.retrieve(stripe_subscription.latest_invoice.to_s)
                                 ^-------
Error: instantiating 'Stripe::Invoice.class#retrieve(String)'


In lib/stripe/src/stripe/methods/core/invoices/retrieve_invoice.cr:8:19

 8 | raise Error.from_json(response.body, "error")
                 ^--------
Error: instantiating 'Stripe::Error.class#from_json(String, String)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/from_json.cr:27:5

 27 | new parser
      ^--
Error: instantiating 'new(JSON::PullParser)'


In lib/stripe/src/stripe/error.cr:2:3

 2 | include JSON::Serializable
     ^
Error: expanding macro


There was a problem expanding macro 'included'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/serialization.cr:133:5

 133 | macro included

Which expanded to:

 >  1 |       # Define a `new` directly in the included type,
 >  2 |       # so it overloads well with other possible initializes
 >  3 | 
 >  4 |       def self.new(pull : ::JSON::PullParser)
 >  5 |         new_from_json_pull_parser(pull)
 >  6 |       end
 >  7 | 
 >  8 |       private def self.new_from_json_pull_parser(pull : ::JSON::PullParser)
 >  9 |         instance = allocate
 > 10 |         instance.initialize(__pull_for_json_serializable: pull)
 > 11 |         GC.add_finalizer(instance) if instance.responds_to?(:finalize)
 > 12 |         instance
 > 13 |       end
 > 14 | 
 > 15 |       # When the type is inherited, carry over the `new`
 > 16 |       # so it can compete with other possible initializes
 > 17 | 
 > 18 |       macro inherited
 > 19 |         def self.new(pull : ::JSON::PullParser)
 > 20 |           new_from_json_pull_parser(pull)
 > 21 |         end
 > 22 |       end
 > 23 |     
Error: instantiating 'new_from_json_pull_parser(JSON::PullParser)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/serialization.cr:159:7

 159 | {% begin %}
       ^
Error: expanding macro


There was a problem expanding macro 'macro_5544074528'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/serialization.cr:159:7

 159 | {% begin %}

Which expanded to:

 >   1 | 
 >   2 |         
 >   3 |         
 >   4 |           
 >   5 |           
 >   6 |             
 >   7 |           
 >   8 |         
 >   9 |           
 >  10 |           
 >  11 |         
 >  12 |           
 >  13 |           
 >  14 |         
 >  15 |           
 >  16 |           
 >  17 |             
 >  18 |           
 >  19 |         
 >  20 |           
 >  21 |           
 >  22 |             
 >  23 |           
 >  24 |         
 >  25 |           
 >  26 |           
 >  27 |             
 >  28 |           
 >  29 |         
 >  30 |           
 >  31 |           
 >  32 |             
 >  33 |           
 >  34 |         
 >  35 |           
 >  36 |           
 >  37 |             
 >  38 |           
 >  39 |         
 >  40 |           
 >  41 |           
 >  42 |             
 >  43 |           
 >  44 |         
 >  45 |           
 >  46 |           
 >  47 |             
 >  48 |           
 >  49 |         
 >  50 |           
 >  51 |           
 >  52 |             
 >  53 |           
 >  54 |         
 >  55 |           
 >  56 |           
 >  57 |             
 >  58 |           
 >  59 |         
 >  60 |           
 >  61 |           
 >  62 |             
 >  63 |           
 >  64 |         
 >  65 | 
 >  66 |         
 >  67 |           __temp_9380 = nil
 >  68 |           __temp_9381 = false
 >  69 |         
 >  70 |           __temp_9382 = nil
 >  71 |           __temp_9383 = false
 >  72 |         
 >  73 |           __temp_9384 = nil
 >  74 |           __temp_9385 = false
 >  75 |         
 >  76 |           __temp_9386 = nil
 >  77 |           __temp_9387 = false
 >  78 |         
 >  79 |           __temp_9388 = nil
 >  80 |           __temp_9389 = false
 >  81 |         
 >  82 |           __temp_9390 = nil
 >  83 |           __temp_9391 = false
 >  84 |         
 >  85 |           __temp_9392 = nil
 >  86 |           __temp_9393 = false
 >  87 |         
 >  88 |           __temp_9394 = nil
 >  89 |           __temp_9395 = false
 >  90 |         
 >  91 |           __temp_9396 = nil
 >  92 |           __temp_9397 = false
 >  93 |         
 >  94 |           __temp_9398 = nil
 >  95 |           __temp_9399 = false
 >  96 |         
 >  97 |           __temp_9400 = nil
 >  98 |           __temp_9401 = false
 >  99 |         
 > 100 | 
 > 101 |         __temp_9402 = pull.location
 > 102 |         begin
 > 103 |           pull.read_begin_object
 > 104 |         rescue exc : ::JSON::ParseException
 > 105 |           raise ::JSON::SerializableError.new(exc.message, self.class.to_s, nil, *__temp_9402, exc)
 > 106 |         end
 > 107 |         until pull.kind.end_object?
 > 108 |           __temp_9403 = pull.location
 > 109 |           key = pull.read_object_key
 > 110 |           case key
 > 111 |           
 > 112 |             when "message"
 > 113 |               __temp_9381 = true
 > 114 |               begin
 > 115 |                 __temp_9380 =
 > 116 |                    pull.read_null_or { 
 > 117 | 
 > 118 |                   
 > 119 | 
 > 120 |                   
 > 121 |                     ::Union((String | Nil)).new(pull)
 > 122 |                   
 > 123 | 
 > 124 |                   
 > 125 | 
 > 126 |                  } 
 > 127 |               rescue exc : ::JSON::ParseException
 > 128 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "message", *__temp_9403, exc)
 > 129 |               end
 > 130 |           
 > 131 |             when "__raven_event_id"
 > 132 |               __temp_9383 = true
 > 133 |               begin
 > 134 |                 __temp_9382 =
 > 135 |                    pull.read_null_or { 
 > 136 | 
 > 137 |                   
 > 138 | 
 > 139 |                   
 > 140 |                     ::Union((String | Nil)).new(pull)
 > 141 |                   
 > 142 | 
 > 143 |                   
 > 144 | 
 > 145 |                  } 
 > 146 |               rescue exc : ::JSON::ParseException
 > 147 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "__raven_event_id", *__temp_9403, exc)
 > 148 |               end
 > 149 |           
 > 150 |             when "__raven_user"
 > 151 |               __temp_9385 = true
 > 152 |               begin
 > 153 |                 __temp_9384 =
 > 154 |                    pull.read_null_or { 
 > 155 | 
 > 156 |                   
 > 157 | 
 > 158 |                   
 > 159 |                     ::Union((AnyHash::JSON | Nil)).new(pull)
 > 160 |                   
 > 161 | 
 > 162 |                   
 > 163 | 
 > 164 |                  } 
 > 165 |               rescue exc : ::JSON::ParseException
 > 166 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "__raven_user", *__temp_9403, exc)
 > 167 |               end
 > 168 |           
 > 169 |             when "__raven_tags"
 > 170 |               __temp_9387 = true
 > 171 |               begin
 > 172 |                 __temp_9386 =
 > 173 |                    pull.read_null_or { 
 > 174 | 
 > 175 |                   
 > 176 | 
 > 177 |                   
 > 178 |                     ::Union((AnyHash::JSON | Nil)).new(pull)
 > 179 |                   
 > 180 | 
 > 181 |                   
 > 182 | 
 > 183 |                  } 
 > 184 |               rescue exc : ::JSON::ParseException
 > 185 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "__raven_tags", *__temp_9403, exc)
 > 186 |               end
 > 187 |           
 > 188 |             when "__raven_extra"
 > 189 |               __temp_9389 = true
 > 190 |               begin
 > 191 |                 __temp_9388 =
 > 192 |                    pull.read_null_or { 
 > 193 | 
 > 194 |                   
 > 195 | 
 > 196 |                   
 > 197 |                     ::Union((AnyHash::JSON | Nil)).new(pull)
 > 198 |                   
 > 199 | 
 > 200 |                   
 > 201 | 
 > 202 |                  } 
 > 203 |               rescue exc : ::JSON::ParseException
 > 204 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "__raven_extra", *__temp_9403, exc)
 > 205 |               end
 > 206 |           
 > 207 |             when "type"
 > 208 |               __temp_9391 = true
 > 209 |               begin
 > 210 |                 __temp_9390 =
 > 211 |                   
 > 212 | 
 > 213 |                   
 > 214 | 
 > 215 |                   
 > 216 |                     Enum::StringConverter(Stripe::Error::Type).from_json(pull)
 > 217 |                   
 > 218 | 
 > 219 |                   
 > 220 | 
 > 221 |                 
 > 222 |               rescue exc : ::JSON::ParseException
 > 223 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "type", *__temp_9403, exc)
 > 224 |               end
 > 225 |           
 > 226 |             when "charge"
 > 227 |               __temp_9393 = true
 > 228 |               begin
 > 229 |                 __temp_9392 =
 > 230 |                    pull.read_null_or { 
 > 231 | 
 > 232 |                   
 > 233 | 
 > 234 |                   
 > 235 |                     ::Union((String | Nil)).new(pull)
 > 236 |                   
 > 237 | 
 > 238 |                   
 > 239 | 
 > 240 |                  } 
 > 241 |               rescue exc : ::JSON::ParseException
 > 242 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "charge", *__temp_9403, exc)
 > 243 |               end
 > 244 |           
 > 245 |             when "code"
 > 246 |               __temp_9395 = true
 > 247 |               begin
 > 248 |                 __temp_9394 =
 > 249 |                    pull.read_null_or { 
 > 250 | 
 > 251 |                   
 > 252 | 
 > 253 |                   
 > 254 |                     ::Union((String | Nil)).new(pull)
 > 255 |                   
 > 256 | 
 > 257 |                   
 > 258 | 
 > 259 |                  } 
 > 260 |               rescue exc : ::JSON::ParseException
 > 261 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "code", *__temp_9403, exc)
 > 262 |               end
 > 263 |           
 > 264 |             when "decline_code"
 > 265 |               __temp_9397 = true
 > 266 |               begin
 > 267 |                 __temp_9396 =
 > 268 |                    pull.read_null_or { 
 > 269 | 
 > 270 |                   
 > 271 | 
 > 272 |                   
 > 273 |                     ::Union((String | Nil)).new(pull)
 > 274 |                   
 > 275 | 
 > 276 |                   
 > 277 | 
 > 278 |                  } 
 > 279 |               rescue exc : ::JSON::ParseException
 > 280 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "decline_code", *__temp_9403, exc)
 > 281 |               end
 > 282 |           
 > 283 |             when "doc_url"
 > 284 |               __temp_9399 = true
 > 285 |               begin
 > 286 |                 __temp_9398 =
 > 287 |                    pull.read_null_or { 
 > 288 | 
 > 289 |                   
 > 290 | 
 > 291 |                   
 > 292 |                     ::Union((String | Nil)).new(pull)
 > 293 |                   
 > 294 | 
 > 295 |                   
 > 296 | 
 > 297 |                  } 
 > 298 |               rescue exc : ::JSON::ParseException
 > 299 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "doc_url", *__temp_9403, exc)
 > 300 |               end
 > 301 |           
 > 302 |             when "param"
 > 303 |               __temp_9401 = true
 > 304 |               begin
 > 305 |                 __temp_9400 =
 > 306 |                    pull.read_null_or { 
 > 307 | 
 > 308 |                   
 > 309 | 
 > 310 |                   
 > 311 |                     ::Union((String | Nil)).new(pull)
 > 312 |                   
 > 313 | 
 > 314 |                   
 > 315 | 
 > 316 |                  } 
 > 317 |               rescue exc : ::JSON::ParseException
 > 318 |                 raise ::JSON::SerializableError.new(exc.message, self.class.to_s, "param", *__temp_9403, exc)
 > 319 |               end
 > 320 |           
 > 321 |           else
 > 322 |             on_unknown_json_attribute(pull, key, __temp_9403)
 > 323 |           end
 > 324 |         end
 > 325 |         pull.read_next
 > 326 | 
 > 327 |         
 > 328 |           
 > 329 | 
 > 330 |           
 > 331 |             
 > 332 |               @message = __temp_9381 ? __temp_9380 : nil
 > 333 |             
 > 334 |           
 > 335 | 
 > 336 |           
 > 337 |         
 > 338 |           
 > 339 | 
 > 340 |           
 > 341 |             
 > 342 |               @__raven_event_id = __temp_9383 ? __temp_9382 : nil
 > 343 |             
 > 344 |           
 > 345 | 
 > 346 |           
 > 347 |         
 > 348 |           
 > 349 | 
 > 350 |           
 > 351 |             
 > 352 |               @__raven_user = __temp_9385 ? __temp_9384 : nil
 > 353 |             
 > 354 |           
 > 355 | 
 > 356 |           
 > 357 |         
 > 358 |           
 > 359 | 
 > 360 |           
 > 361 |             
 > 362 |               @__raven_tags = __temp_9387 ? __temp_9386 : nil
 > 363 |             
 > 364 |           
 > 365 | 
 > 366 |           
 > 367 |         
 > 368 |           
 > 369 | 
 > 370 |           
 > 371 |             
 > 372 |               @__raven_extra = __temp_9389 ? __temp_9388 : nil
 > 373 |             
 > 374 |           
 > 375 | 
 > 376 |           
 > 377 |         
 > 378 |           
 > 379 |             if __temp_9390.nil? && !__temp_9391 && !::Union(Stripe::Error::Type).nilable?
 > 380 |               raise ::JSON::SerializableError.new("Missing JSON attribute: type", self.class.to_s, nil, *__temp_9402, nil)
 > 381 |             end
 > 382 |           
 > 383 | 
 > 384 |           
 > 385 |             @type = (__temp_9390).as(Stripe::Error::Type)
 > 386 |           
 > 387 | 
 > 388 |           
 > 389 |         
 > 390 |           
 > 391 | 
 > 392 |           
 > 393 |             
 > 394 |               @charge = __temp_9393 ? __temp_9392 : nil
 > 395 |             
 > 396 |           
 > 397 | 
 > 398 |           
 > 399 |         
 > 400 |           
 > 401 | 
 > 402 |           
 > 403 |             
 > 404 |               @code = __temp_9395 ? __temp_9394 : nil
 > 405 |             
 > 406 |           
 > 407 | 
 > 408 |           
 > 409 |         
 > 410 |           
 > 411 | 
 > 412 |           
 > 413 |             
 > 414 |               @decline_code = __temp_9397 ? __temp_9396 : nil
 > 415 |             
 > 416 |           
 > 417 | 
 > 418 |           
 > 419 |         
 > 420 |           
 > 421 | 
 > 422 |           
 > 423 |             
 > 424 |               @doc_url = __temp_9399 ? __temp_9398 : nil
 > 425 |             
 > 426 |           
 > 427 | 
 > 428 |           
 > 429 |         
 > 430 |           
 > 431 | 
 > 432 |           
 > 433 |             
 > 434 |               @param = __temp_9401 ? __temp_9400 : nil
 > 435 |             
 > 436 |           
 > 437 | 
 > 438 |           
 > 439 |         
 > 440 |       
Error: instantiating '(AnyHash::JSON | Nil).class#new(JSON::PullParser)'


In /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/from_json.cr:291:3

 291 | {% begin %}
       ^
Error: expanding macro


There was a problem expanding macro 'macro_5544541136'

Called macro defined in /Users/stephen/.asdf/installs/crystal/0.36.1/src/json/from_json.cr:291:3

 291 | {% begin %}

Which expanded to:

 >  1 | 
 >  2 |     
 >  3 |     
 >  4 | 
 >  5 |     # If after traversing all the types we are left with just one
 >  6 |     # non-primitive type, we can parse it directly (no need to use `read_raw`)
 >  7 |     
 >  8 |       return AnyHash::JSON.new(pull)
 >  9 |     
 > 10 |   
Error: instantiating 'AnyHash::JSON.class#new(JSON::PullParser)'


In lib/any_hash/src/any_hash.cr:146:30

 146 | @__hash__ = self.class.deep_cast_value(hash).as(Hash(K, V))
                              ^--------------
Error: instantiating 'AnyHash::JSON.class#deep_cast_value(JSON::PullParser)'


In lib/any_hash/src/any_hash.cr:74:7

 74 | value.as(V)
      ^
Error: can't cast JSON::PullParser to AnyHash::JSONTypes::Value

Sija commented

It seems that for some reason these properties aren't ignored...

Sija commented

Does Exception itself has include JSON::Serializable?

It actually didn't, but adding it still throws the same compiler error. If you'd like, I'd be happy to add you as a contributor on the private repo so that you could pull the code/branch and poke around? Also happy to hop on Discord if you'd like to chat through this in more real time.

Sija commented

@stephendolan Sounds great, I'd be happy to help you debug it. re: discord you can find me by the username sija#1765.

After discussing, this can be resolved quite simply by extending the Extensionclass in your application to ignore the fields added by Raven.cr, like so:

# config/raven.cr
 class Exception
  @[JSON::Field(ignore: true)]
  @__raven_event_id : String?

  {% for key in %i(user tags extra) %}
    @[JSON::Field(ignore: true)]
    @__raven_{{ key.id }} : AnyHash::JSON?
  {% end %}
end

Raven.configure do |config|
  # all the stuff...
end

That said, I'll be leaving this issue open so that I can upstream the changes in a PR that will support ignoring these fields both with JSON and YAML.