#13: Custom Error Pages in Phoenix

Elixir 1.4

Phoenix 1.2.1

Source code on GitHub


Here we have a phoenix app, but when someone goes to a page that doesn’t exist our app returns a NoRouteError.

Let’s see what this error would look like in if we had deployed our app and one of our users saw it.

The first thing we’ll need to do is go into our config directory and open the ‘dev.exs’ file.

In order to display error pages, we’ll change debug_errors to false.

config/dev.exs

config :teacher, Teacher.Endpoint,
  http: [port: 4000],
  debug_errors: false,
  …

With this change we’ll need to restart our server.

$ mix phoenix.server

And if we go back to our browser and refresh the page, we see a message is returned: “Page not found”.

In this episode we’ll create custom 404 and 500 pages for the application, so let’s get started.

Now this error message is rendered from the the ErrorView, so let’s open up that file.

We can see when it receives a 404 or a 500 it displays a message.

We’ll update these to instead render a template.

For the 404 let’s render a template we’ll call “404_page.html” and for our 500 we’ll render another template named “500_page.html”.

web/views/error_view.ex

defmodule Teacher.ErrorView do
  use Teacher.Web, :view

  def render("404.html", _assigns) do
    render("404_page.html", %{})
  end

  def render("500.html", _assigns) do
    render("500_page.html", %{})  
  end
  …
end

Now let’s create our two templates.

We’ll create a new directory in our templates directory named “error” and inside it we’ll create the matching templates “404_page.html.eex” and “500_page.html.eex”.

I’ve filled the contents of these off screen, but you we can see they are full HTML documents. This is because our error templates our not rendered through our application’s layout.

Template path: web/templates/error/404_page.html.eex

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Nothing to see here</title>
    <link rel="stylesheet" href="/css/app.css">
  </head>
  <body>
    <div class="container">
      <main role="main">
        <h2>404 - Nothing to see here</h2>
      </main>
    </div> <!-- /container -->
  </body>
</html>

Template path: web/templates/error/500_page.html.eex

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>There was an error</title>
    <link rel="stylesheet" href="/css/app.css">
  </head>
  <body>
    <div class="container">
      <main role="main">
        <h2>500 - There was an error</h2>
      </main>
    </div> <!-- /container -->
  </body>
</html>

And with that let’s go back to our browser and if we trigger an error or go to a page that doesn’t exist, we see our custom error templates are now being rendered, perfect.