<p><strong>404 redirect:</strong></p>

<p>You could set up your single to use <code>404-not-found</code> (example) as a uri, and add a redirect:</p>

<pre><code>{% redirect '/404-not-found' %}
</code></pre>

<p>to the <code>/404.html</code> file. That way every 404-page gets redirected to the single.</p>

<p><em>Downside:</em> You will loose the 404-header, and the uri in the address-bar will be lost.</p>

<p>.</p>

<p><strong>Load Single:</strong></p>

<p>Set up a single, and load the single entry into the <code>/404.html</code> file:</p>

<pre><code>{% set entry = craft.section('404-single-handle').first() %}
</code></pre>

<p>Now you can use the entry-var just like you would in a normal single template.</p>

<p>You will have to use a single-uri, but you could add a conditional to the single template (not the 404.html), which redirects to index if it gets accessed directly:</p>

<pre><code>{% redirect '/' %}
</code></pre>

<p>.</p>

<p><strong>EDIT:</strong> I didn't know a single can be set to 404 without breaking the functionality, so Brandon's answer is the way to go ;)</p>

CC BY-SA 3.0
2014-06-21T21:11:08.490Z
2014-06-21T21:24:37.003Z
2014-06-21T21:24:37.003Z
Victor
<p>This is something I discuss in the <a href="https://nystudio107.com/blog/handling-errors-gracefully-in-craft-cms#handling-exceptions-on-the-frontend" rel="nofollow noreferrer">Handling Errors Gracefully in Craft CMS</a> article, not just for 404s, but for a number of different status codes/errors.</p>

<p>The actual templating code then ends up looking something like this for <code>error.twig</code>:</p>

<pre><code>{# @var craft \craft\web\twig\variables\CraftVariable #}
{% set entry = craft.entries.section("genericError").one() %}

{% extends "_layouts/errors" %}

{% block _inline_css %}
    &lt;style&gt;
        {{ source ("errors/error_critical.min.css", ignore_missing = true) }}
    &lt;/style&gt;
{% endblock %}
</code></pre>

<p>I use a separate layout template for all of the errors (because they mostly look the same, an image and a message coming from a Single), so here is the <code>errors.twig</code> layout:</p>

<pre><code>{# The layout template for error pages #}
{# @var craft \craft\web\twig\variables\CraftVariable #}
{% extends "_layouts/site" %}

{% block main %}

    &lt;section&gt;
        &lt;div class="bg-white flex flex-wrap mt-30 md:mt-85 xl:mt-85"
             id="properties"&gt;
            &lt;div class="w-full mt-45 md:mt-120 xl:mt-180 text-center"&gt;
                &lt;img src="{{ entry.errorImage.one().url }}"/&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/section&gt;

    &lt;section&gt;
        &lt;div class="bg-white flex flex-wrap" id="properties"&gt;
            &lt;div class="w-full my-45 md:my-120 xl:my-180"&gt;
                &lt;h3 class="text-center font-surv-disp font-normal text-ss-blue-dark text-24 md:text-30 lg:text-38 mb-45"&gt;
                    {{ entry.errorMessage }}
                &lt;/h3&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/section&gt;

{% endblock %}

{% block _inline_js %}
{% endblock %}
</code></pre>

<p>Which just displays the generic information, and extends the overall <code>site.twig</code> layout.</p>

CC BY-SA 4.0
2018-07-25T19:10:09.183Z
2018-07-25T19:10:09.183Z
andrew.welch
<p>I would create a Single with the URI set to "404", and also set its Template to "404". That entry will automatically get loaded if you go to <a href="http://example.com/404" rel="noreferrer">http://example.com/404</a>, and load your 404.html template, so at the top of the template you should add this to it:</p>

<pre><code>{#
 #  Fetch the 404 Single entry, if we don’t already have it.
 #  (requests to /404 will already have it.)
 #}
{% if entry is not defined %}
    {% set entry = craft.entries.uri('404').first() %}
{% endif %}
</code></pre>

<p><strong>Craft 3 note:</strong> As of Craft 3 the 404.html template is only loaded if <code>devMode</code> is <em>disabled</em> in the current environment. If <code>devMode</code> is <em>enabled</em>, you'll continue get a Yii error message.</p>

CC BY-SA 3.0
2014-06-21T21:28:27.047Z
That works pretty well, only problem is if you hit /404 it doesn't have the 404 header. Not the end of the world, but would be nice.
Jeremy Gimbel
CC BY-SA 3.0
2014-06-21T21:30:14.203Z
You could add a redirect to a non-existing page (e.g. 404-not-found), if last segment is 404. Not a clean solution, but you'd get a 404 header ;)
Victor
CC BY-SA 3.0
2014-06-21T21:33:30.363Z
@JeremyGimbel That was already the case, and it’s pretty common behavior (if you’re trying to directly access the 404 page, and you get the 404 page, you technically got exactly what you wanted). See https://github.com/404 for example. If you really don’t like that, you could add this before that conditional: `{% if entry is defined %}{% exit 404 %}{% endif %}`
Brandon Kelly
CC BY-SA 4.0
2018-07-20T18:23:31.547Z
Does this not work in Craft 3? I've tried adding templates/404.html and templates/_404.html. Either way when I go to mysite.com/not-a-page I get a "Template not found: not-a-page" error.
Simon Kuran
CC BY-SA 4.0
2018-08-04T16:52:44.080Z
@SimonKuran In Craft 3 the 404 template will only show when Dev Mode is disabled.
Brandon Kelly
CC BY-SA 4.0
2018-08-04T16:57:14.227Z
@BrandonKelly Thanks for replying. I figured it out. I added that note to your answer. Adding a note to the docs under “5.” might be handy. https://docs.craftcms.com/v3/routing.html#dynamic-routes
Simon Kuran
CC BY-SA 4.0
2018-08-04T18:31:37.457Z
@SimonKuran good idea! Just updated that.
Brandon Kelly
CC BY-SA 4.0
2014-06-21T21:23:01.513Z
2018-07-25T18:32:54.323Z
2018-07-25T18:32:54.323Z
Brandon Kelly
<p>I'd like to make my 404 page editable through Craft, but when I create a single for it, a URI is required. </p>

<p>Is there a way to make a single with no URI, or is the best route to setup globals for managing this content? Or is there a better way that I don't know about?</p>

<singles><404-page><error-templates>
What's the best way to set up a content-manageable 404 page?
# What's the best way to set up a content-manageable 404 page?

(Asked by: username_0 on 2014-06-21)

I'd like to make my 404 page editable through Craft, but when I create a single for it, a URI is required.

Is there a way to make a single with no URI, or is the best route to setup globals for managing this content? Or is there a better way that I don't know about?

**Tags:** singles, 404-page, error-templates


---

## 3 answers

### Answer by username_3 on 2014-06-21. Score: 20 | Accepted answer

I would create a Single with the URI set to "404", and also set its Template to "404". That entry will automatically get loaded if you go to http://example.com/404, and load your 404.html template, so at the top of the template you should add this to it:
{#
 #  Fetch the 404 Single entry, if we don’t already have it.
 #  (requests to /404 will already have it.)
 #}
{% if entry is not defined %}
    {% set entry = craft.entries.uri('404').first() %}
{% endif %}

Craft 3 note: As of Craft 3 the 404.html template is only loaded if devMode is disabled in the current environment. If devMode is enabled, you'll continue get a Yii error message.

> **Comments:**
> **username_0**: That works pretty well, only problem is if you hit /404 it doesn't have the 404 header. Not the end of the world, but would be nice.  
> **username_1**: You could add a redirect to a non-existing page (e.g. 404-not-found), if last segment is 404. Not a clean solution, but you'd get a 404 header ;)  
> **username_3**: @JeremyGimbel That was already the case, and it’s pretty common behavior (if you’re trying to directly access the 404 page, and you get the 404 page, you technically got exactly what you wanted). See https://github.com/404 for example. If you really don’t like that, you could add this before that conditional: `{% if entry is defined %}{% exit 404 %}{% endif %}`  
> **username_4**: Does this not work in Craft 3? I've tried adding templates/404.html and templates/_404.html. Either way when I go to mysite.com/not-a-page I get a "Template not found: not-a-page" error.  
> **username_3**: @SimonKuran In Craft 3 the 404 template will only show when Dev Mode is disabled.  
> **username_4**: @BrandonKelly Thanks for replying. I figured it out. I added that note to your answer. Adding a note to the docs under “5.” might be handy. https://docs.craftcms.com/v3/routing.html#dynamic-routes  
> **username_3**: @SimonKuran good idea! Just updated that.  

---

### Answer by username_1 on 2014-06-21. Score: 2

404 redirect:
You could set up your single to use 404-not-found (example) as a uri, and add a redirect:
{% redirect '/404-not-found' %}

to the /404.html file. That way every 404-page gets redirected to the single.
Downside: You will loose the 404-header, and the uri in the address-bar will be lost.
.
Load Single:
Set up a single, and load the single entry into the /404.html file:
{% set entry = craft.section('404-single-handle').first() %}

Now you can use the entry-var just like you would in a normal single template.
You will have to use a single-uri, but you could add a conditional to the single template (not the 404.html), which redirects to index if it gets accessed directly:
{% redirect '/' %}

.
EDIT: I didn't know a single can be set to 404 without breaking the functionality, so Brandon's answer is the way to go ;)


---

### Answer by username_2 on 2018-07-25. Score: 1

This is something I discuss in the Handling Errors Gracefully in Craft CMS article, not just for 404s, but for a number of different status codes/errors.
The actual templating code then ends up looking something like this for error.twig:
{# @var craft \craft\web\twig\variables\CraftVariable #}
{% set entry = craft.entries.section("genericError").one() %}

{% extends "_layouts/errors" %}

{% block _inline_css %}
    
{% endblock %}

I use a separate layout template for all of the errors (because they mostly look the same, an image and a message coming from a Single), so here is the errors.twig layout:
{# The layout template for error pages #}
{# @var craft \craft\web\twig\variables\CraftVariable #}
{% extends "_layouts/site" %}

{% block main %}

    
        
            
                
            
        
    

    
        
            
                
                    {{ entry.errorMessage }}
                
            
        
    

{% endblock %}

{% block _inline_js %}
{% endblock %}

Which just displays the generic information, and extends the overall site.twig layout.


---

