I am encountering a 404 error on the last page of a category archive when using WP_Query
for pagination in WordPress 6.8. I'm seeking insights into the cause of this issue and potential solutions.
Environment:
WordPress Version: 6.8
PHP Version: 8.4.6
MySQL Version: Ver 15.1 Distrib 10.11.11-MariaDB, for debian-linux-gnu (x86_64) using EditLine wrapper
Server Version: Apache/2.4.62 (Debian)
Issue occurs on both local and remote (shared hosting) server environments.
Themes Tested: Twenty Twenty-Five, Twenty Twenty-Four, Twenty Twenty-Three (all default themes)
No plugins are active during testing.
The issue has been tested while logged in and logged out.
Steps to Reproduce:
Create a new database and perform a clean installation of WordPress 6.8.
Log in to the WordPress admin dashboard.
Create a new category (e.g., "food").
Create 11 posts and assign them to the "food" category.
Create a file named
category-food.php
in the active theme's directory.Navigate to "Settings" > "Reading" and leave the "Blog pages show at most" option set to 10.
Save permalinks (even without changes) and verify the
.htaccess
file.
Expected Behavior:
Pagination should function correctly, allowing access to all pages of the category archive.
The last page should display the remaining posts based on the
posts_per_page
parameter inWP_Query
without returning a 404 error./category/food/page/1/
: Should display 4 posts./category/food/page/2/
: Should display 4 posts./category/food/page/3/
: Should display 3 posts (total of 11 posts).
Actual Behavior:
/category/food/page/1/
: Displays 4 posts./category/food/page/2/
: Displays 4 posts./category/food/page/3/
: Returns a 404 error page.The issue only occurs when accessing the last page of the pagination.
Modifying the arguments of
WP_Query
does not resolve the fundamental issue.Setting the "Blog pages show at most" option in "Settings" > "Reading" to the same value as the
posts_per_page
argument inWP_Query
prevents the error.
category-food.php
Code:
<?php
get_header();
global $post;
$paged = get_query_var('paged') ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'post',
'category_name' => 'food',
'no_found_rows' => false,
'post_status' => 'publish',
'posts_per_page' => 4,
'paged' => $paged,
);
echo '<pre>WP_Query Args (Before):</pre>';
echo '<pre>';
print_r($args);
echo '</pre>';
$the_query = new WP_Query($args);
print_r('paged:' . $paged . ', ' . $args['paged'] . '/' . $the_query->max_num_pages . ', found_posts:' . $the_query->found_posts);
if ($args['paged'] == $the_query->max_num_pages) {
// The last page is not reached when not logged in
// var_dump($the_query);
echo '<p>' . $paged . ' page</p>';
}
$html = '<ul>';
if ($the_query->have_posts()) {
$posts = $the_query->posts; // Get the array of retrieved post objects
foreach ($posts as $p) {
$the_query->the_post(); // Set up the global $post variable
$html .= '<li><h3>' . esc_html(get_the_title()) . '</h3></li>';
}
$html .= '</ul>';
} else {
return 'Recent shortcode: no posts matched your criteria.';
}
// Restore original Post Data.
wp_reset_postdata();
echo $html;
get_footer();