404s are not triggering my 404.php template. The header status code, checked in firebug, is a 404, but the page that gets displayed is like a loop with 0 items (as if this were simply an archive page with 0 entries).

If my permalinks start with /%year%/ and I go to bla.com/9999 (which should produce a 404), WP Debug shows the request as a year:

Request: 9999
Query String: year=9999
Matched Rewrite Rule: ([0-9]{4})/?$
Matched Rewrite Query: year=9999

If my permalinks start with /%category%/ and I go to bla.com/zzzzz (which should produce a 404), WP Debug shows the request as a category_name:

Request: zzzzz
Query String: category_name=zzzzz
Matched Rewrite Rule: (.+?)/?$
Matched Rewrite Query: category_name=zzzzz

What's going on? The Show Template plugin (which prints an html comment telling you what template was used to render the page) tells me that the page is rendering with the index.php template. How can I get my 404.php template to load?

  • This seems like something that extension code might break. Disable all plugins, switch to default theme and check if that makes a difference.
    – Rarst
    Sep 7, 2011 at 22:16
  • Changing to another theme eliminates the problem, but what sort of thing should I be looking for in my original thing to fix this? I built it, based on the Boilerplate theme, and I don't have very many actions hooked into the header.
    – supertrue
    Sep 7, 2011 at 22:53
  • Sorry I do not have a good guess. Just try same approach with theme - remove hooked stuff to nothing and if it helps add back piece by piece.
    – Rarst
    Sep 8, 2011 at 7:19

1 Answer 1


I found that the problem was with the otherwise very useful plugin Legacy URL Forwarding.

It uses the following function (abridged here) with the 404_template hook.

function doUrlForwarding() {

// make a $query based on the $_SERVER['REQUEST_URI']

// if a post is found, redirect to it
   if (!empty($query->post->ID)) {
      wp_redirect(get_permalink($query->post->ID), '301' );


With the above hook active, the 404.php does not get fired. However, if I place doUrlForwarding at the top of 404.php, it works correctly.

This answers the mystery, but I still don't know why using the 404_template hook is preventing the 404.php template from loading on normal 404s. Comment if you have an idea.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.