I’ve recently had a load of WordPress work.
Much of these jobs are similar, so I’ve had a good chance to try and learn more about better theme and plugin design.
One of these sites had a strange error when paginating the posts page. Permalinks were set to Day and Name
, with the category base set to news
and blog index set to the news
page.
This creates the illusion of a standard site with all news namespaced under /news
.
Calling mysite.com/news
gave the first page of posts, using the index.php
template file. Calling mysite.com/news/my-category/
gave the latest posts within that category, and pagination worked correctly when calling mysite.com/news/my-category/page/2
.
But, annoyingly, calling mysite.com/news/page/2
gave a 404 error.
I googled far and wide but could not find an exact match to my problem (although it seems to be common with custom post types).
Changing permalinks back to the default setting worked, so I left it at that so I could dig deeper.
After some googling I found a recommendation to use the Debug This plugin. It gives detailed breakdowns of debugging data on any page or post. I was only interested in the rewrite rules so this is as far as I got with it.
Using Debug This to list the rewrite rules, I could see which one was being matched and what the redirect was doing in the background. It’s done with the Debug This menu item, and selecting Query > Rewrites.
When I called mysite.com/news
this was the output:
Matched Rule: (.?.+?)(/[0-9]+)?/?$
Matched Query: pagename=news&page=
Calling mysite.com/news/my-category/
gave:
Matched Rule: news/(.+?)/?$
Matched Query: category_name=my-category
And mysite.com/news/my-category/page/2
gave:
Matched Rule: news/(.+?)/page/?([0-9]{1,})/?$
Matched Query: category_name=my-category&paged=2
Strangely mysite.com/news/page/2
did not match any rules. So the quickest option was to add my own rule to get things going again.
The third matched rule above is close to what I want, just without the category part of the url. So news/page/?([0-9]{1,})/?$
should work OK, provided that it was checked before the other rules.
In functions.php
I added the following code:
function mg_news_pagination_rewrite() {
add_rewrite_rule(get_option('category_base').'/page/?([0-9]{1,})/?$', 'index.php?pagename='.get_option('category_base').'&paged=$matches[1]', 'top');
}
add_action('init', 'mg_news_pagination_rewrite');
This simply adds a rewrite rule for pagination of the category_base
value.
I added top
as a third argument to insert the rule at the beginning of the list. It would otherwise match news/(.+?)/?$
(as it did originally) where it would throw a 404 error after failing to find a page
category.
I’ve purposely used get_option('category_base')
instead of news
here too, so you can copy and paste into your own functions.php
file.
The Source of the Problem
After writing this post I tried to replicate this on a fresh install, to see if it’s a problem within WordPress or not.
Setting the blog index to a static page, e.g. blog
, works fine. Posts are viewed under /blog
and pagination works automatically, following the standard blog/page/2
pattern.
The problem arose as I had the category base set to news
.
The WordPress rewrite rule list has the category rewrites at the beginning, followed by tags, comments, author, posts by date etc, then finally the wildcards for pages. You can view a sample full list of rules on the WordPress plugin API pages.
In this case news
was right at the top, so the match was made before reaching the page wildcard rules.
This is how it’s meant to happen, and my trick to imitate a sub directory of news would not work by design.
However, I think that the solution above is valid.
2 replies on “Fixing a WordPress pagination 404 error”
[…] Note: This article was originally written by Mei Gwilym on Aug 19, 2015. […]
[…] will cease to work beyond page 1, but instead will generate 404 errors. This snippet from Meigwilym.com offers a nice solution for […]