Where can I see the Plug.Parsers.ParseError when they are raised?

Yesterday I was building a simple Elixir app using cowboy and Plug, and was trying to fix a strange issue. My POST requests with JSON body was simply… disappearing.

It took me an hour of poking at wrong places to find out that I actually forgot to add poison dependency, which I was using as JSON decoder, in mix.exs. Once I fetched that dependency, it worked as expected.

The strange thing was that the error message was not being shown anywhere. After tinkering with it a bit more, I found out that Plug.Parsers.ParseError would not show up in trace even with poison dependency added.

This seems like a reasonable decision, since I wouldn’t want my error log to be overwhelmed by all the errors from http requests with incorrectly formatted JSON. Well, aside from a minor issue that cowboy automatically sends 500 Internal Server Error status when 400 Bad Request is more appropriate in this case.

But I’m curious about how the error was not being propagated up the stack trace and/or process supervision tree. Where is it going? Where is it being caught and discarded? How is it being discarded? Can someone help me look into this?

1 Like

I’m pretty sure it is being passed to the ErrorView render functions, the error exception should be in the assigns.reason considering I have code like this:

  def render("403.html", assigns) do
    case assigns[:reason] do
      %Perms.PermissionException{} = exc ->
        Logger.warn("Permission Error of #{inspect exc.permission} due to #{inspect assigns[:conn]}")
        "Forbidden due to permission error:  #{exc.message}"
      _ -> "Forbidden"

Although this specific render function is no longer called since I added a plug (no way to redirect from a view, there really should be…) that redirects to the login page on a permission error. ^.^

Exceptions will be a status 500 by default, but you can add a plug_status member or override a protocol to specify whatever status you want an exception to be. I have plug_status’s on all my exceptions. :slight_smile:

Now if only we could specify a protocol or something that acts as a controller level callback for an exception instead of going straight to the view, hmm, that might actually be pretty easy to do now that I think of it, will require a controller override plug (I already have a few of those, wrapping a controller handler is not so fun…).

1 Like

Thanks to your hints, I started digging more into it with tools like :debugger. Then I found Plug.Debugger and Plug.ErrorHandler that allow me to have a better look at the errors - they would come quite handy when I want to look at errors from Plug. I think I will stop venturing into this rabbit hole for now. Thank you for helping!

1 Like