I am making a category template page with pagination and below is my code:

$current_page = get_queried_object();
$category     = $current_page->slug;

$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$query = new WP_Query(
        'paged'         => $paged,
        'category_name' => $category,
        'order'         => 'asc',
        'post_type'     => 'page',
        'post_status' => array('publish'),
        'posts_per_page' => 6,
        'post_parent' => 2,

if ($query->have_posts()) {
       while ($query->have_posts()) {
       $query->the_post(); ?>

        <article id="post-<?php the_ID(); ?>">
            <header class="entry-header">
                <?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
            </header><!-- .entry-header -->

            <div class="entry-content">
                <?php the_content(); ?>
            </div><!-- .entry-content -->
        </article><!-- #post-## --><hr>


    // next_posts_link() usage with max_num_pages
    next_posts_link( 'Older Entries', $query->max_num_pages );
    previous_posts_link( 'Newer Entries' );


So I have about 10 pages with the same category (e.g. arts).

And I will get the next page link from next_posts_link( 'Older Entries', $query->max_num_pages );. It generates link like this:


But I get a 404 page when I click on this url above. It should stays at the category template, shouldn't it?

So I added the following fix into functions.php:

add_action( 'init', 'wpa58471_category_base' );
function wpa58471_category_base() {
    // Remember to flush the rules once manually after you added this code!
        // The regex to match the incoming URL
        // The resulting internal URL
        // Add the rule to the top of the rewrite list
        'top' );

But I still get the 404 page. What have I done wrong?

Even if I access it with the direct address, I still get 404:


Any ideas why?

  • Why do you create a new query in the template instead of using the default main query?
    – Milo
    Mar 12, 2018 at 14:59
  • @Milo i need to customise it further. that is just a simplified version.
    – Run
    Mar 12, 2018 at 15:02
  • 404 is based on the results of the main query, you need to alter it with pre_get_posts, not create a new one in the template.
    – Milo
    Mar 12, 2018 at 15:52
  • @Milo thanks but it does not make sense, nor is constructive without an example.
    – Run
    Mar 12, 2018 at 16:13
  • if you search this site for pre_get_posts you will find many similar questions with answers.
    – Milo
    Mar 12, 2018 at 16:16

2 Answers 2


The steps WordPress takes to serve a front end request are roughly-

  1. The incoming URL is parsed and converted to query vars.

  2. These query vars form the Main Query, which is sent to the database.

  3. WordPress looks at the results and determines if the request was successful or not, which determines what status header to send- 200 OK, or 404 not found.

  4. WordPress loads the template that corresponds to this type of request, for example, a category archive template in the case of your category request, or the 404 template, in the case the main query has no posts.

So the shortest answer to your question as to why you are seeing a 404, is that the main query has no posts.

The query you run in the template and whatever pagination it generates is irrelevant to the main query. This is why you need to alter the main query with pre_get_posts to customize the results of an archive page.

If you just want pages, you can set post type to just page:

add_action( 'pre_get_posts', function($q) {
    if( !is_admin() && $q->is_main_query() && !$q->is_tax() ) {
        $q->set ('post_type', array( 'page' ) );

This how I fix this problem:

// Fix 404 on category pagination.
// https://teamtreehouse.com/community/wordpress-pagination-gives-404-unless-i-set-blog-pages-show-at-most-to-1-in-reading
add_action( 'pre_get_posts', function($q) {
    if( !is_admin() && $q->is_main_query() && !$q->is_tax() ) {
        $q->set ('post_type', array( 'post', 'page' ) );

Pagination is meant for posts only I guess. So I must add page to the post_type.

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.