WordPress: The template_redirect Hook Returns 404

Hey there! I'm currently working on a CLI tool to deploy WordPress apps to DigitalOcean. Check it out! It's free and open source.

This is a real quick one. I’ve started using the W3 Total Cache plugin a few days ago which I’m totally satisfied with. Unlike the WP Super Cache plugin, W3TC can keep the caches in memory via memcached, serve the static content through CDNs. The guys at W3 Edge promised to add Amazon CloudFront compatibility which I’m very excited about. As we all know (I guess) Mashable is running WordPress, and guess what! They’re using W3 Total Cache too, so if they could trust those guys, then I’m totally in. Their support over Twitter is awesome, you don’t even have to look for them! Just tweet your problem mentioning “W3 Total Cache” or “W3TC” – they’ll find you via search and help you solve whatever your issue is.

Anyways, that being said, after writing my post announcements to Twitter via Twitter Friendly Links some peeps shouted out that I was returning 404 errors on all of my short links. Strange, thought I, as I was able to see everything fine. Looking at the settings of the plugin I realized that I, as a logged in user, weren’t looking at cached pages, so I turned that off and guess what! I got those 404s. Creepy! After a little talk over Twitter and IM with the guys at W3 Edge, I started to look through the caching plugin code. It’s so well-written and I’ve actually learned a couple of techniques out there! Anyways, the reason I was getting 404s was because W3 TC looked at the $wp_query object and it’s $is_404 variable, which I don’t know why (Frederick from W3 Edge mentioned a redirection issue with WordPress) was returning true on all of my Twitter friendly links!

I figured out that the template_redirect hook (which is not documented in the WordPress Codex at all) didn’t quite do what I wanted it to. The easiest way out was adding a couple of lines before the redirect actually happened:

global $wp_query;
$wp_query->is_404 = false;

And guess what, it worked! This may be not the smartest decission but hey, it’s working! One more workaround would be adding a regular expression to the W3 Total Cache page settings, exclude “[0-9]+/?$” which would not cache any .com/1234 queries, but that’s not so reliable for a couple of reasons. First, why not cache if we can cache? And second, what if we’re using Twitter Friendly Links in alphanumeric mode? That would mean “[0-9a-zA-Z]+/?$” which would probably match for all the other top-level pages, thus we’re losing all the benefits from caching. Meh!

I guess this is not the only place where the template_redirect action would return a 404. Some plugins that define their own permalinks through the template_redirect hook (WP Polls for poll results for instance, not sure though) will also get 404s if they don’t set it to false in $wp_query. Many wordpress websites have profile pages which are not actual pages in the database, but are handled through the template_redirect action for .com/profile_name sort of permalinks which is indeed cool. I’m actually planning on using it with one of my upcoming projects and I’m really glad I sorted it out.

So the big shoutout goes to W3 Total Cache and the W3 Edge team!

About the author

Konstantin Kovshenin

WordPress Core Contributor, ex-Automattician, public speaker and consultant, enjoying life in Moscow. I blog about tech, WordPress and DevOps.


  • I like your writing style. I'll bet even people who aren't into the code could benefit from reading your blog.

    Incidentally, there are several WP hooks and functions that aren't documented. I wonder why that is?

    • Thank you Aaron, much appreciated.

      You see, the WordPress documentation (Codex) is just like Wikipedia, it's built by everybody (although maintained by the WordPress guys) but describing a certain function or a certain hook is not enough. There are a few rules to follow when writing into the Codex, this includes writing working examples, describing the code, formatting everything, which indeed may take a lot of time, thus some sections are left blank, especially ones that are not frequently used.

      Perhaps we guys, that like to dig deeper than the Template Functions should write that unfinished part of the Codex, but then again, that's quite a big amount of time, plus the rules are annoying to read ;)

      Hope that explains it :) Thanks again.

    • Well, going off of Lorelle, anything is better than nothing. I don't usually follow the "rules" and someone else usually comes by and corrects anything that I might have missed.

      As long as the content is WordPress related and useful, no one is going to get onto you for writing content.

  • Any plugin which extends the permalink structure has to do something like this. template_redirect is literally the last thing that happens before WP outputs a page, and by that time WP has already decided it's a 404 (since the core doesn't know about your extension). So if your plugin is going to output something, it also needs to tell WP that it isn't a 404.

    • Yeah, there are still issues though with some caching plugins, that's why I switched over to direct .htaccess caching, hope to get rid of the template_redirect hook.