When you set WordPress up with:
The set-up
Custom Permalink Structure: /blog/%postname%/
Category base: blog
Generated rewrite rules
WordPress generates these rewrite rules:
- blog/([^/]+)(?:/([0-9]+))?/?$ => index.php?name=$matches[1]&page=$matches[2]
- blog/(.+?)/?$ => index.php?category_name=$matches[1]
Rewrite rule position in the rewrite_rules_array
Your post rewrite rule (#1) is positioned earlier (therefore higher priority) than the category rewrite rule (#2) in your rewrite_rules_array. This allows your post URLs to work and causes your category URLs to fail.
Where the rewrite rule is positioned in the rewrite_rules_array matters.
Similar regular expression pattern
The regular expression in your post rewrite rule (#1) matches both mydomain.com/blog/my-post
and mydomain.com/blog/my-category
. So, when you attempt to visit https://example.com/blog/<category_name>
, WordPress does this:
Using this:
blog/([^/]+)(?:/([0-9]+))?/?$ => index.php?name=$matches[1]&page=$matches[2]
converts this:
https://example.com/blog/some-category
into this:
index.php?name=some-category&page=
(page is automatically added by WordPress for front-page pagination).
Since name is in the query string, WordPress searches for a post with post_name (slug) of some-category and tries to display it using a single post template (e.g. single.html). This likely results in a 404 (not found) page. The desired outcome is to have WordPress recognize some-category as a category_name and display the results using a category archive template (e.g. category.html).
Solution
Using a WP_Rewrite->front (blog) and a matching Category base (blog) violates conventional WordPress configuration. WordPress uses a different front for different items: category for category, tag for tag. Notice that WordPress does not use the front category for both category and tag. Also, keep in mind the list of WordPress Reserved Terms.
If you must adhere to this non-conventional set-up, you should be able to do it using the template_redirect action hook. The idea is to test is_404()
to see if the situation presented under Similar regular expression pattern has occurred. If it did, run a new WP_Query with arguments that look for results using the category_name parameter. The remainder of your solution is found in the answer to this question in WordPress Stack Exchange: Load a specific post if user tries to access 404 page. Be careful to set the appropriate conditional tag property (is_category) to true.