Search code examples
elixirphoenix-frameworkdialyzer

Custom Exceptions and type specs


In elixir you can define a custom exception like this:

defmodule AppWeb.CustomError do
  defexception message: "some custom server error", plug_status: 500
end

But this is not an Elixir.Exception anymore

So if you use it with a third party library which has this kind of type spec defined:

  @spec capture_exception(Exception.t, Keyword.t) :: task
  def capture_exception(exception, opts \\ []) do

  ...

  Sentry.capture_exception(AppWeb.CustomError,
                         [stacktrace: System.stacktrace()]

The dialyzer will crash with breaks the contract because the CustomError is not an Exception:

The call 'Elixir.Sentry':capture_exception('Elixir.AppWeb.CustomError',[{'stacktrace',[{atom(),atom(),[any()] | byte(),[{'file',string()} | {'line',pos_integer()}]}]},...]) breaks the contract ('Elixir.Exception':t(),'Elixir.Keyword':t()) -> task()

Can you somehow extend Elixir.Exception module within AppWeb.CustomError? or how can this be taken care following best practices?


Solution

  • You're passing the module name (AppWeb.CustomError) instead of an instance of it (%AppWeb.CustomError{}). An instance of the module will satisfy the Exception.t type.

    Sentry.capture_exception(%AppWeb.CustomError{},
                             [stacktrace: System.stacktrace()]