I've a very simple index.php:

<div id="content">
  <? get_template_part('content', get_post_format()) ?>

<div id="pagination">
  <? previous_posts_link() ?>
  <? next_posts_link() ?>

And my content.php looks roughly like this:

$paged = get_query_var('paged') ? get_query_var('paged') : 1;
  'post_type' => ['articles', 'projects', 'tips'],
  'orderby' => 'date',
  'posts_per_page' => 7,
  'paged' => $paged

<? while(have_posts()): the_post() ?>
  <article class="post">
    <h2><? the_title() ?></h2>
    <p><? the_excerpt() ?></p>
      <? foreach($categories as $cat): ?>
      <li class="category"><a href="#"><?= $cat->name ?></a></li>
      <? endforeach ?>
<? endwhile ?>

There are 14 posts in total but the "next" posts is always redirecting to a 404 on /page/2 instead of showing the remaining 7 posts.

Edit: If I use a custom WP_Query instead of query_posts then the next and previous links won't even show. https://gist.github.com/elclanrs/4782705

I've been trying to find a solution to this issue since yesterday. I'm aware of all the other questions similar to this one, but for my particular set-up none of the solutions I found worked, including:

I'm also aware of pre_get_posts but I would like to know what's the problem with my current setup. Any ideas?

2 Answers 2


By the time you reach the template, WordPress has already queried the database and decided what to display based on those results.

You're seeing a 404 error because based on the default main query, there are no more posts to show.

When you call query_posts in the template, you overwrite that original query. Despite the fact that your new query results contain more posts, WordPress has no awareness of this modified query.

This is why you should never use query_posts in the template. You've provided the solution to your issue already, use the pre_get_posts action to modify the main query before it happens.

  • I understand...But why wouldn't it work with a custom WP_query. I tried like this as well: gist.github.com/elclanrs/4782705 but it doesn't even show the prev/next links. Apparently people are getting it working with the solutions I found and a custom query but it doesn't seem to be working for me.
    – elclanrs
    Feb 13, 2013 at 1:04
  • pre_get_posts is the best way to modify your query anyway as it means you only query the database 1 time instead of adding a second query. Feb 13, 2013 at 1:17
  • @helgatheviking: I got it working with pre_get_posts already I was just wondering why my solution didn't work but anyway it's working now with the hook.
    – elclanrs
    Feb 13, 2013 at 1:20
  • @elclanrs it doesn't work for the same reason. the 404 is from an entirely different query, one based solely on the requested page, not the result of a custom query or call to query_posts. there are certain circumstances where it won't result in a 404, for example if you were to do a custom query within a page post type, but your main posts page and post type or taxonomy archive pages can't reliably have the query modified in the template.
    – Milo
    Feb 13, 2013 at 1:20
  • @Milo: Oh that clarifies things a bit. Will use pre_get_posts from now on.
    – elclanrs
    Feb 13, 2013 at 1:22

Another solution that worked for me if using the Custom Post Type UI plugin, was to alter the rewrite settings in the interface for the custom post type.

For example, I had a custom 'news' post type, no issues other than pagination wouldn't work (e.g. /news/page/2 would 404). The two solutions I found were to either:

  • Turn the 'Rewrite' setting to false (resulting in news article URLs like domain.co.uk/?=title-of-news-article)
  • Or keep the 'Rewrite' setting to true, but use a custom slug, like in my case 'newsstory', which solves the 404 and then rewrites the article URLs to be domain.co.uk/newsstory/title-of-news-article

Ultimately, though, I imagine the above is just a fix if your listing page is called the same as your post type. E.g. the page by 'news' post type was showing on, had the slug 'news' too so this could have confused matters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.