Trigger 404 page in WordPress

Sometimes you need to throw a 404 if certain conditions are met and doing so in WordPress requires a little trickery to achieve the full effect.

I don’t want to go into a discussion about whether this would ever be correct behaviour but I will say this: if a URL is sometimes not found, that means it is sometimes found and if so, a different HTTP Status Code in the 4xx category would probably be more applicable, e.g. 401 if your condition is whether the user is logged in, or 405 if there’s a GET where only a POST is allowed. In this case, wp_die() would be a more sensible decision.

That said, there are odd occasions when this will be useful and I leave it to you to make such a judgement.

How it works

Throwing a 404 in WordPress requires 5 main steps:

  1. Make is_* functions return correct values: e.g. is_404() should return true and is_archive() should return false
  2. Ensure HTML title is correct: Depending on the request and your theme, the <title> might not always change
  3. Throw HTTP Status Code 404: A 404 page needs to return 404, or it’ll be what’s called a “Soft 404”, which are misleading
  4. Show the 404 template: The user needs to be shown the 404 page (because this isn’t all about machines!)
  5. Stop execution: WordPress will want to continue with the request so exit; ensures nothing shows after the 404 template

The Code

function fourohfour() {

    // 1. Ensure `is_*` functions work
    global $wp_query;
    $wp_query->set_404();

    // 2. Fix HTML title
    add_action( 'wp_title', function () {
        return '404: Not Found';
    }, 9999 );

    // 3. Throw 404
    status_header( 404 );
    nocache_headers();

    // 4. Show 404 template
    require get_404_template();

    // 5. Stop execution
    exit;

}

Conclusion

As aforementioned, it’s very unlikely this would ever be desirable behaviour, but never say never!

2 Comments

    • To use this in your `functions.php` just paste the function in there and then call it with `fourohfour()`.

      For example, if you want to really infuriate your users you could do something like `if (time() % 2) { fourohfour(); }` :P

Leave a Reply

Your email address will not be published.