ErrorMessage (error_message v0.1.3) View Source

ErrorMessage

Test Hex pm

This library exists to simplify error systems in a code base and allow for a simple unified experience when using and reading error messages around the code base

This creates one standard, that all errors should fit into the context of HTTP error codes, if they don't :internal_server_error should be used and you can use the message and details to provide a further level of depth

Installation

The package can be installed by adding error_message to your list of dependencies in mix.exs:

def deps do
  [
    {:error_message, "~> 0.1.0"}
  ]
end

Documentation can be found at https://hexdocs.pm/error_message.

Usage Example

iex> id = 1
iex> ErrorMessage.not_found("no user with id #{id}", %{user_id: id})
%ErrorMessage{
  code: :not_found,
  message: "no user with id 1",
  details: %{user_id: 1}
}

iex> ErrorMessage.internal_server_error("critical internal error", %{
...>   reason: :massive_issue_with_x
...> })
%ErrorMessage{
  code: :internal_server_error,
  message: "critical internal error",
  details: %{reason: :massive_issue_with_x}
}

Why is this important

If we want to have a good way to catch errors around our system as well as be able to display errors that happen throughout our system, it's useful to have a common error api so we can predict what will come out of a system

For example if we used elixir through our server, we would be able to catch a not found pretty easily since we can predict the error code coming in without needing to know the message. This leads to more resilliant code since message changes won't break the functionality of your application

# Because our error system is setup with `find_user` we can easily
# catch no users and have a solid backup plan
with {:error, %ErrorMessage{code: :not_found}} <- find_user(%{name: "bill"}) do
  create_user(%{name: "bill"})
end

Usage with Phoenix

Another benefit is error rendering to the frontend, because all our errors are part of the HTTP error system, it's quite easy to now return the proper status codes and messages to our frontend clients. For example:

defmodule MyController do
  def index(conn, param) do
    case find_thing(params) do
      {:ok, res} -> json(conn, res)
      {:error, e} -> json_error(conn, e)
    end
  end

  defp json_error(conn, %ErrorMessage{code: code} = e) do
    conn
      |> put_status(code) # Plug.Conn
      |> json(ErrorMessage.to_jsonable_map(e))
  end
end

Usage with Logger

Ontop of being useful for Phoenix we can also find some good use from this system and Logger, since ErrorMessage implements String.Chars protocol

case do_thing() do
  {:ok, value} -> {:ok, do_other_thing(value)}
  {:error, e} = res ->
    Logger.error("[MyModule] \#{e}")
    Logger.warn(to_string(e))

    res
end

Link to this section Summary

Functions

Create bad_gateway error message

Create bad_request error message

Create conflict error message

Create expectation_failed error message

Create failed_dependency error message

Create forbidden error message

Create found error message

Create gateway_timeout error message

Create gone error message

Create http_version_not_supported error message

Create im_a_teapot error message

Converts an %ErrorMessage{} struct into an inspectable version

Create insufficient_storage error message

Create internal_server_error error message

Create length_required error message

Create locked error message

Create loop_detected error message

Create method_not_allowed error message

Create misdirected_request error message

Create moved_permanently error message

Create multiple_choices error message

Create network_authentication_required error message

Create not_acceptable error message

Create not_extended error message

Create not_found error message

Create not_implemented error message

Create not_modified error message

Create payment_required error message

Create permanent_redirect error message

Create precondition_failed error message

Create precondition_required error message

Create proxy_authentication_required error message

Create request_entity_too_large error message

Create request_header_fields_too_large error message

Create request_timeout error message

Create request_uri_too_long error message

Create requested_range_not_satisfiable error message

Create see_other error message

Create service_unavailable error message

Create switch_proxy error message

Create temporary_redirect error message

Converts an %ErrorMessage{} struct to a map and makes sure that the contents of the details map can be converted to json

Converts an %ErrorMessage{} struct to a string formatted error message

Create too_early error message

Create too_many_requests error message

Create unauthorized error message

Create unavailable_for_legal_reasons error message

Create unprocessable_entity error message

Create unsupported_media_type error message

Create upgrade_required error message

Create use_proxy error message

Create variant_also_negotiates error message

Link to this section Types

Specs

code() ::
  :multiple_choices
  | :moved_permanently
  | :found
  | :see_other
  | :not_modified
  | :use_proxy
  | :switch_proxy
  | :temporary_redirect
  | :permanent_redirect
  | :bad_request
  | :unauthorized
  | :payment_required
  | :forbidden
  | :not_found
  | :method_not_allowed
  | :not_acceptable
  | :proxy_authentication_required
  | :request_timeout
  | :conflict
  | :gone
  | :length_required
  | :precondition_failed
  | :request_entity_too_large
  | :request_uri_too_long
  | :unsupported_media_type
  | :requested_range_not_satisfiable
  | :expectation_failed
  | :im_a_teapot
  | :misdirected_request
  | :unprocessable_entity
  | :locked
  | :failed_dependency
  | :too_early
  | :upgrade_required
  | :precondition_required
  | :too_many_requests
  | :request_header_fields_too_large
  | :unavailable_for_legal_reasons
  | :internal_server_error
  | :not_implemented
  | :bad_gateway
  | :service_unavailable
  | :gateway_timeout
  | :http_version_not_supported
  | :variant_also_negotiates
  | :insufficient_storage
  | :loop_detected
  | :not_extended
  | :network_authentication_required

Specs

t() :: %ErrorMessage{code: code(), details: any(), message: String.t()}

Specs

t_map() :: %{code: code(), message: String.t(), details: any()}

Link to this section Functions

Specs

bad_gateway(message :: String.t()) :: t()

Create bad_gateway error message

Example

iex>

Link to this function

bad_gateway(message, details)

View Source

Specs

bad_gateway(message :: String.t(), details :: any()) :: t()

Specs

bad_request(message :: String.t()) :: t()

Create bad_request error message

Example

iex>

Link to this function

bad_request(message, details)

View Source

Specs

bad_request(message :: String.t(), details :: any()) :: t()

Specs

conflict(message :: String.t()) :: t()

Create conflict error message

Example

iex>

Link to this function

conflict(message, details)

View Source

Specs

conflict(message :: String.t(), details :: any()) :: t()
Link to this function

expectation_failed(message)

View Source

Specs

expectation_failed(message :: String.t()) :: t()

Create expectation_failed error message

Example

iex>

Link to this function

expectation_failed(message, details)

View Source

Specs

expectation_failed(message :: String.t(), details :: any()) :: t()
Link to this function

failed_dependency(message)

View Source

Specs

failed_dependency(message :: String.t()) :: t()

Create failed_dependency error message

Example

iex>

Link to this function

failed_dependency(message, details)

View Source

Specs

failed_dependency(message :: String.t(), details :: any()) :: t()

Specs

forbidden(message :: String.t()) :: t()

Create forbidden error message

Example

iex>

Link to this function

forbidden(message, details)

View Source

Specs

forbidden(message :: String.t(), details :: any()) :: t()

Specs

found(message :: String.t()) :: t()

Create found error message

Example

iex>

Specs

found(message :: String.t(), details :: any()) :: t()
Link to this function

gateway_timeout(message)

View Source

Specs

gateway_timeout(message :: String.t()) :: t()

Create gateway_timeout error message

Example

iex>

Link to this function

gateway_timeout(message, details)

View Source

Specs

gateway_timeout(message :: String.t(), details :: any()) :: t()

Specs

gone(message :: String.t()) :: t()

Create gone error message

Example

iex>

Specs

gone(message :: String.t(), details :: any()) :: t()
Link to this function

http_version_not_supported(message)

View Source

Specs

http_version_not_supported(message :: String.t()) :: t()

Create http_version_not_supported error message

Example

iex>

Link to this function

http_version_not_supported(message, details)

View Source

Specs

http_version_not_supported(message :: String.t(), details :: any()) :: t()

Specs

im_a_teapot(message :: String.t()) :: t()

Create im_a_teapot error message

Example

iex>

Link to this function

im_a_teapot(message, details)

View Source

Specs

im_a_teapot(message :: String.t(), details :: any()) :: t()

Specs

inspect(error_message :: t()) :: String.t()

Converts an %ErrorMessage{} struct into an inspectable version

## Example

iex> ErrorMessage.inspect(ErrorMessage.not_found("couldn't find user", %{user_id: "as21fasdfJ"}))
"#ErrorMessage<code: :not_found, message: \"couldn't find user\">\nDetails: %{user_id: \"as21fasdfJ\"}"
Link to this function

insufficient_storage(message)

View Source

Specs

insufficient_storage(message :: String.t()) :: t()

Create insufficient_storage error message

Example

iex>

Link to this function

insufficient_storage(message, details)

View Source

Specs

insufficient_storage(message :: String.t(), details :: any()) :: t()
Link to this function

internal_server_error(message)

View Source

Specs

internal_server_error(message :: String.t()) :: t()

Create internal_server_error error message

Example

iex>

Link to this function

internal_server_error(message, details)

View Source

Specs

internal_server_error(message :: String.t(), details :: any()) :: t()
Link to this function

length_required(message)

View Source

Specs

length_required(message :: String.t()) :: t()

Create length_required error message

Example

iex>

Link to this function

length_required(message, details)

View Source

Specs

length_required(message :: String.t(), details :: any()) :: t()

Specs

locked(message :: String.t()) :: t()

Create locked error message

Example

iex>

Link to this function

locked(message, details)

View Source

Specs

locked(message :: String.t(), details :: any()) :: t()

Specs

loop_detected(message :: String.t()) :: t()

Create loop_detected error message

Example

iex>

Link to this function

loop_detected(message, details)

View Source

Specs

loop_detected(message :: String.t(), details :: any()) :: t()
Link to this function

method_not_allowed(message)

View Source

Specs

method_not_allowed(message :: String.t()) :: t()

Create method_not_allowed error message

Example

iex>

Link to this function

method_not_allowed(message, details)

View Source

Specs

method_not_allowed(message :: String.t(), details :: any()) :: t()
Link to this function

misdirected_request(message)

View Source

Specs

misdirected_request(message :: String.t()) :: t()

Create misdirected_request error message

Example

iex>

Link to this function

misdirected_request(message, details)

View Source

Specs

misdirected_request(message :: String.t(), details :: any()) :: t()
Link to this function

moved_permanently(message)

View Source

Specs

moved_permanently(message :: String.t()) :: t()

Create moved_permanently error message

Example

iex>

Link to this function

moved_permanently(message, details)

View Source

Specs

moved_permanently(message :: String.t(), details :: any()) :: t()
Link to this function

multiple_choices(message)

View Source

Specs

multiple_choices(message :: String.t()) :: t()

Create multiple_choices error message

Example

iex>

Link to this function

multiple_choices(message, details)

View Source

Specs

multiple_choices(message :: String.t(), details :: any()) :: t()
Link to this function

network_authentication_required(message)

View Source

Specs

network_authentication_required(message :: String.t()) :: t()

Create network_authentication_required error message

Example

iex>

Link to this function

network_authentication_required(message, details)

View Source

Specs

network_authentication_required(message :: String.t(), details :: any()) :: t()

Specs

not_acceptable(message :: String.t()) :: t()

Create not_acceptable error message

Example

iex>

Link to this function

not_acceptable(message, details)

View Source

Specs

not_acceptable(message :: String.t(), details :: any()) :: t()

Specs

not_extended(message :: String.t()) :: t()

Create not_extended error message

Example

iex>

Link to this function

not_extended(message, details)

View Source

Specs

not_extended(message :: String.t(), details :: any()) :: t()

Specs

not_found(message :: String.t()) :: t()

Create not_found error message

Example

iex>

Link to this function

not_found(message, details)

View Source

Specs

not_found(message :: String.t(), details :: any()) :: t()
Link to this function

not_implemented(message)

View Source

Specs

not_implemented(message :: String.t()) :: t()

Create not_implemented error message

Example

iex>

Link to this function

not_implemented(message, details)

View Source

Specs

not_implemented(message :: String.t(), details :: any()) :: t()

Specs

not_modified(message :: String.t()) :: t()

Create not_modified error message

Example

iex>

Link to this function

not_modified(message, details)

View Source

Specs

not_modified(message :: String.t(), details :: any()) :: t()
Link to this function

payment_required(message)

View Source

Specs

payment_required(message :: String.t()) :: t()

Create payment_required error message

Example

iex>

Link to this function

payment_required(message, details)

View Source

Specs

payment_required(message :: String.t(), details :: any()) :: t()
Link to this function

permanent_redirect(message)

View Source

Specs

permanent_redirect(message :: String.t()) :: t()

Create permanent_redirect error message

Example

iex>

Link to this function

permanent_redirect(message, details)

View Source

Specs

permanent_redirect(message :: String.t(), details :: any()) :: t()
Link to this function

precondition_failed(message)

View Source

Specs

precondition_failed(message :: String.t()) :: t()

Create precondition_failed error message

Example

iex>

Link to this function

precondition_failed(message, details)

View Source

Specs

precondition_failed(message :: String.t(), details :: any()) :: t()
Link to this function

precondition_required(message)

View Source

Specs

precondition_required(message :: String.t()) :: t()

Create precondition_required error message

Example

iex>

Link to this function

precondition_required(message, details)

View Source

Specs

precondition_required(message :: String.t(), details :: any()) :: t()
Link to this function

proxy_authentication_required(message)

View Source

Specs

proxy_authentication_required(message :: String.t()) :: t()

Create proxy_authentication_required error message

Example

iex>

Link to this function

proxy_authentication_required(message, details)

View Source

Specs

proxy_authentication_required(message :: String.t(), details :: any()) :: t()
Link to this function

request_entity_too_large(message)

View Source

Specs

request_entity_too_large(message :: String.t()) :: t()

Create request_entity_too_large error message

Example

iex>

Link to this function

request_entity_too_large(message, details)

View Source

Specs

request_entity_too_large(message :: String.t(), details :: any()) :: t()
Link to this function

request_header_fields_too_large(message)

View Source

Specs

request_header_fields_too_large(message :: String.t()) :: t()

Create request_header_fields_too_large error message

Example

iex>

Link to this function

request_header_fields_too_large(message, details)

View Source

Specs

request_header_fields_too_large(message :: String.t(), details :: any()) :: t()
Link to this function

request_timeout(message)

View Source

Specs

request_timeout(message :: String.t()) :: t()

Create request_timeout error message

Example

iex>

Link to this function

request_timeout(message, details)

View Source

Specs

request_timeout(message :: String.t(), details :: any()) :: t()
Link to this function

request_uri_too_long(message)

View Source

Specs

request_uri_too_long(message :: String.t()) :: t()

Create request_uri_too_long error message

Example

iex>

Link to this function

request_uri_too_long(message, details)

View Source

Specs

request_uri_too_long(message :: String.t(), details :: any()) :: t()
Link to this function

requested_range_not_satisfiable(message)

View Source

Specs

requested_range_not_satisfiable(message :: String.t()) :: t()

Create requested_range_not_satisfiable error message

Example

iex>

Link to this function

requested_range_not_satisfiable(message, details)

View Source

Specs

requested_range_not_satisfiable(message :: String.t(), details :: any()) :: t()

Specs

see_other(message :: String.t()) :: t()

Create see_other error message

Example

iex>

Link to this function

see_other(message, details)

View Source

Specs

see_other(message :: String.t(), details :: any()) :: t()
Link to this function

service_unavailable(message)

View Source

Specs

service_unavailable(message :: String.t()) :: t()

Create service_unavailable error message

Example

iex>

Link to this function

service_unavailable(message, details)

View Source

Specs

service_unavailable(message :: String.t(), details :: any()) :: t()

Specs

switch_proxy(message :: String.t()) :: t()

Create switch_proxy error message

Example

iex>

Link to this function

switch_proxy(message, details)

View Source

Specs

switch_proxy(message :: String.t(), details :: any()) :: t()
Link to this function

temporary_redirect(message)

View Source

Specs

temporary_redirect(message :: String.t()) :: t()

Create temporary_redirect error message

Example

iex>

Link to this function

temporary_redirect(message, details)

View Source

Specs

temporary_redirect(message :: String.t(), details :: any()) :: t()
Link to this function

to_jsonable_map(error_message)

View Source

Specs

to_jsonable_map(error_message :: t()) :: t_map()

Converts an %ErrorMessage{} struct to a map and makes sure that the contents of the details map can be converted to json

## Example

iex> ErrorMessage.to_jsonable_map(ErrorMessage.not_found("couldn't find user", %{user_id: "as21fasdfJ"}))
%{code: :not_found, message: "couldn't find user", details: %{user_id: "as21fasdfJ"}}

iex> error = ErrorMessage.im_a_teapot("teapot", %{
...>   user: %{health: {:alive, 500}},
...>   test: %TestStruct{a: [Date.new!(2020, 1, 10)]}
...> })
iex> ErrorMessage.to_jsonable_map(error)
%{
  code: :im_a_teapot,
  message: "teapot",
  details: %{
    user: %{health: [:alive, 500]},
    test: %{struct: "ErrorMessageTest.TestStruct", data: %{a: ["2020-01-10"]}}
  }
}
Link to this function

to_string(error_message)

View Source

Specs

to_string(error_message :: t()) :: String.t()

Converts an %ErrorMessage{} struct to a string formatted error message

## Example

iex> ErrorMessage.to_string(ErrorMessage.internal_server_error("Something bad happened", %{result: :unknown}))
"internal_server_error - Something bad happened\nDetails: %{result: :unknown}"

Specs

too_early(message :: String.t()) :: t()

Create too_early error message

Example

iex>

Link to this function

too_early(message, details)

View Source

Specs

too_early(message :: String.t(), details :: any()) :: t()
Link to this function

too_many_requests(message)

View Source

Specs

too_many_requests(message :: String.t()) :: t()

Create too_many_requests error message

Example

iex>

Link to this function

too_many_requests(message, details)

View Source

Specs

too_many_requests(message :: String.t(), details :: any()) :: t()

Specs

unauthorized(message :: String.t()) :: t()

Create unauthorized error message

Example

iex>

Link to this function

unauthorized(message, details)

View Source

Specs

unauthorized(message :: String.t(), details :: any()) :: t()
Link to this function

unprocessable_entity(message)

View Source

Specs

unprocessable_entity(message :: String.t()) :: t()

Create unprocessable_entity error message

Example

iex>

Link to this function

unprocessable_entity(message, details)

View Source

Specs

unprocessable_entity(message :: String.t(), details :: any()) :: t()
Link to this function

unsupported_media_type(message)

View Source

Specs

unsupported_media_type(message :: String.t()) :: t()

Create unsupported_media_type error message

Example

iex>

Link to this function

unsupported_media_type(message, details)

View Source

Specs

unsupported_media_type(message :: String.t(), details :: any()) :: t()
Link to this function

upgrade_required(message)

View Source

Specs

upgrade_required(message :: String.t()) :: t()

Create upgrade_required error message

Example

iex>

Link to this function

upgrade_required(message, details)

View Source

Specs

upgrade_required(message :: String.t(), details :: any()) :: t()

Specs

use_proxy(message :: String.t()) :: t()

Create use_proxy error message

Example

iex>

Link to this function

use_proxy(message, details)

View Source

Specs

use_proxy(message :: String.t(), details :: any()) :: t()
Link to this function

variant_also_negotiates(message)

View Source

Specs

variant_also_negotiates(message :: String.t()) :: t()

Create variant_also_negotiates error message

Example

iex>

Link to this function

variant_also_negotiates(message, details)

View Source

Specs

variant_also_negotiates(message :: String.t(), details :: any()) :: t()