How to use Plug.ErrorHandler to handle errors

Hi.

I’m working on a webapp based only on bandit and plugs only and I’m wondering how to handle errors.

For 404 I can put something like

  match _ do
    ErrorController.error_404(conn)
  end

at the end of the routes list, but that doesn’t catch all other error, as for example 500. This morning I saw there was a dedicated plug to handle error, yet the documentation is pretty short… And since then I’m struggling to understand how to use it.

My router looks like this:

defmodule MEC.Web.Router do

  @moduledoc false
  use Plug.Router
  use Plug.ErrorHandler

  
  require Logger
  alias MEC.Web.PageController
  alias MEC.Web.ErrorController
  
  plug Plug.Logger
  plug :match
  plug :dispatch
  
  get "/", do: PageController.index(conn)
  get "/test", do: FakeController.index(conn)  # NOT DEFINED. To simulate an error 500
  
##   match _ do
##     ErrorController.error_404(conn)
##   end
  
  defp handle_errors(conn, %{kind: kind, reason: reason, stack: _stack}) do
    resp = """
Something went wrong:
  kind=#{inspect(kind)}
  reason=#{inspect(reason)}
  conn=#{inspect(conn, pretty: true)}
"""
    send_resp(conn, conn.status, resp)
  end
  
end

Notice that match _ do is commented to check how ErrorHandler handles 404 errors and the controller FakeController is not defined at all to simulate an error 500.

  • for /: as it is not an error, all is fine
  • for /test : I get an error 500 (only seen in conn.status) which is OK
  • for /other which sould be an error 404, I get a 500 with the reason being reason=%FunctionClauseError{module: MEC.Web.Router, function: :do_match, arity: 4, kind: nil, args: nil, clauses: nil}

This is where I’m stuck. Any hint is welcome

Plug.Router does not handle the 404 by default according to the docs.

This also means that a catch all match block is recommended to be defined as in the example above, otherwise routing fails with a function clause error (as it would in any regular Elixir function).

And this is exactly what you are seeing.