How do I programmatically generate a 404?

All we need is an easy explanation of the problem, so here it is.

How can I get something like this to work?

// in a plugin / theme:
// This imaginary function will make WordPress think that the 
// current request is a 404. 
// Ideally this function could be ran anywhere, but realistically it
// will probably have to be before the template_redirect hook runs.
generate_404_somehow();

// later...
add_action('template_redirect', function() {
    // should be "true"
    var_dump(is_404());
});

Basically under certain conditions, I want to tell WordPress to show its 404 template (which I can hook into later if I want) instead of the template it’s about to load (eg a page or archive).

I know I could just do a 302 redirect to a non-existent page but that’s very messy. I could also send a 404 HTTP header manually, but then I can’t use WP’s nice 404 page (I already have things that hook into is_404() that need to get fired at the right time).

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

function generate_404_somehow() {
   global $wp_query;
   $wp_query->is_404 = true;
}
add_action('wp','generate_404_somehow');

Of course, that will send all of you page to the 404 template. I don’t know what the conditions are that this should fire or not fire.

Or to be more cautious (see comments) …

function generate_404_somehow() {
   global $wp_query;
   $wp_query->set_404();
}
add_action('wp','generate_404_somehow');

Method 2

The other by s_ha_dum answers doesn’t set the HTTP Header Status to 404 Not Found. To do this adds status_header( 404 ) to the function.

function generate_404_somehow() {
    global $wp_query;
    $wp_query->set_404();
    status_header( 404 );
}
add_action('wp','generate_404_somehow');

Method 3

What seems to work:

global $wp_query;
$wp_query->set_404();
$wp_query->max_num_pages = 0; // stop theme from showing Next/Prev links

This seems to set the HTTP headers and load the right template (with is_404() being true).

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply