{"__v":0,"_id":"5777c96e5b2b430e00b982c6","category":{"version":"5777c9635b2b430e00b982a5","project":"54348ec95b10711400c6c445","_id":"5777c9635b2b430e00b982aa","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2014-12-03T21:36:49.014Z","from_sync":false,"order":4,"slug":"bonus-guides","title":"Bonus Guides"},"parentDoc":null,"project":"54348ec95b10711400c6c445","user":"5435e00ad7d8700800bbec51","version":{"__v":1,"_id":"5777c9635b2b430e00b982a5","project":"54348ec95b10711400c6c445","createdAt":"2016-07-02T14:02:11.084Z","releaseDate":"2016-07-02T14:02:11.084Z","categories":["5777c9635b2b430e00b982a6","5777c9635b2b430e00b982a7","5777c9635b2b430e00b982a8","5777c9635b2b430e00b982a9","5777c9635b2b430e00b982aa"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.2.0","version":"1.2.0"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2014-12-03T22:15:51.679Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"never","params":[],"url":""},"isReference":false,"order":8,"body":"Phoenix provides an `ErrorView`, `web/views/error_view.ex`, to render errors in our applications. The full module name will include the name of our application, as in `HelloPhoenix.ErrorView`.\n\nPhoenix will detect any 400 or 500 status level errors in our application and use the `render/2` function in our `ErrorView` to render an appropriate error template. We get default implementations for 404 and 500 HTML errors, but we can add any clauses to `render/2` that we might need. Any errors which don't match an existing clause of `render/2` will be caught by `template_not_found/2`.\n\nWe can also customize the implementation of any of these functions however we like.\n\nHere's what the `ErrorView` looks like.\n\n```elixir\ndefmodule HelloPhoenix.ErrorView do\n  use HelloPhoenix.Web, :view\n\n  def render(\"404.html\", _assigns) do\n    \"Page not found\"\n  end\n\n  def render(\"500.html\", _assigns) do\n    \"Server internal error\"\n  end\n\n  # In case no render clause matches or no\n  # template is found, let's render it as 500\n  def template_not_found(_template, assigns) do\n    render \"500.html\", assigns\n  end\nend\n```\n\n> NOTE: In the development environment, this behavior will be overridden. Instead, we will get a really great debugging page. In order to see the `ErrorView` in action, we'll need to set `debug_errors:` to `false` in `config/dev.exs`. The server must be restarted for the changes to become effective.\n\n```elixir\nconfig :hello_phoenix, HelloPhoenix.Endpoint,\n  http: [port: 4000],\n  debug_errors: false,\n  code_reloader: true,\n  cache_static_lookup: false,\n  watchers: [node: [\"node_modules/brunch/bin/brunch\", \"watch\"]]\n```\n\nTo learn more about custom error pages, please see [The Error View](http://www.phoenixframework.org/docs/views#section-the-errorview) section of the View Guide.\n\n#### Custom Errors\n\nElixir provides a macro called `defexception` for defining custom exceptions. Exceptions are represented as structs, and structs need to be defined inside of modules.\n\nIn order to create a custom error, we need to define a new module. Conventionally this will have \"Error\" in the name. Inside of that module, we need to define a new exception with `defexception`.\n\nWe can also define a module within a module to provide a namespace for the inner module.\n\nHere's an example from the [Phoenix.Router](https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/router.ex) which demonstrates all of these ideas.\n\n```elixir\ndefmodule Phoenix.Router do\n  defmodule NoRouteError do\n    :::at:::moduledoc \"\"\"\n    Exception raised when no route is found.\n    \"\"\"\n    defexception plug_status: 404, message: \"no route found\", conn: nil, router: nil\n\n    def exception(opts) do\n      conn   = Keyword.fetch!(opts, :conn)\n      router = Keyword.fetch!(opts, :router)\n      path   = \"/\" <> Enum.join(conn.path_info, \"/\")\n\n      %NoRouteError{message: \"no route found for #{conn.method} #{path} (#{inspect router})\",\n      conn: conn, router: router}\n    end\n  end\n. . .\nend\n```\n\nPlug provides a protocol called `Plug.Exception` specifically for adding a status to exception structs.\n\nIf we wanted to supply a status of 404 for an `Ecto.NoResultsError`, we could do it by defining an implementation for the `Plug.Exception` protocol like this:\n\n```elixir\ndefimpl Plug.Exception, for: Ecto.NoResultsError do\n  def status(_exception), do: 404\nend\n```\n\nNote that this is just an example: Phoenix [already does this](https://github.com/phoenixframework/phoenix_ecto/blob/master/lib/phoenix_ecto/plug.ex) for `Ecto.NoResultsError`, so you don't have to.","excerpt":"","slug":"custom-errors","type":"basic","title":"Custom Errors"}
Phoenix provides an `ErrorView`, `web/views/error_view.ex`, to render errors in our applications. The full module name will include the name of our application, as in `HelloPhoenix.ErrorView`. Phoenix will detect any 400 or 500 status level errors in our application and use the `render/2` function in our `ErrorView` to render an appropriate error template. We get default implementations for 404 and 500 HTML errors, but we can add any clauses to `render/2` that we might need. Any errors which don't match an existing clause of `render/2` will be caught by `template_not_found/2`. We can also customize the implementation of any of these functions however we like. Here's what the `ErrorView` looks like. ```elixir defmodule HelloPhoenix.ErrorView do use HelloPhoenix.Web, :view def render("404.html", _assigns) do "Page not found" end def render("500.html", _assigns) do "Server internal error" end # In case no render clause matches or no # template is found, let's render it as 500 def template_not_found(_template, assigns) do render "500.html", assigns end end ``` > NOTE: In the development environment, this behavior will be overridden. Instead, we will get a really great debugging page. In order to see the `ErrorView` in action, we'll need to set `debug_errors:` to `false` in `config/dev.exs`. The server must be restarted for the changes to become effective. ```elixir config :hello_phoenix, HelloPhoenix.Endpoint, http: [port: 4000], debug_errors: false, code_reloader: true, cache_static_lookup: false, watchers: [node: ["node_modules/brunch/bin/brunch", "watch"]] ``` To learn more about custom error pages, please see [The Error View](http://www.phoenixframework.org/docs/views#section-the-errorview) section of the View Guide. #### Custom Errors Elixir provides a macro called `defexception` for defining custom exceptions. Exceptions are represented as structs, and structs need to be defined inside of modules. In order to create a custom error, we need to define a new module. Conventionally this will have "Error" in the name. Inside of that module, we need to define a new exception with `defexception`. We can also define a module within a module to provide a namespace for the inner module. Here's an example from the [Phoenix.Router](https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/router.ex) which demonstrates all of these ideas. ```elixir defmodule Phoenix.Router do defmodule NoRouteError do @moduledoc """ Exception raised when no route is found. """ defexception plug_status: 404, message: "no route found", conn: nil, router: nil def exception(opts) do conn = Keyword.fetch!(opts, :conn) router = Keyword.fetch!(opts, :router) path = "/" <> Enum.join(conn.path_info, "/") %NoRouteError{message: "no route found for #{conn.method} #{path} (#{inspect router})", conn: conn, router: router} end end . . . end ``` Plug provides a protocol called `Plug.Exception` specifically for adding a status to exception structs. If we wanted to supply a status of 404 for an `Ecto.NoResultsError`, we could do it by defining an implementation for the `Plug.Exception` protocol like this: ```elixir defimpl Plug.Exception, for: Ecto.NoResultsError do def status(_exception), do: 404 end ``` Note that this is just an example: Phoenix [already does this](https://github.com/phoenixframework/phoenix_ecto/blob/master/lib/phoenix_ecto/plug.ex) for `Ecto.NoResultsError`, so you don't have to.