I have a custom post type which displays posts just fine on the page when I use a custom wp_query however, that breaks pagination, so I tried to use pre_get_posts instead as I'm already using that to handle pagination offsets and that works find on normal posts.

When I try to use pre_get_posts to set the post type for a particular page/post-type though, it shows a 404. I did have a custom post in there with the same string in the name as the custom post type; 'business-challenges' is the post type and 'facing-business-challenges' was the post it redirected to. Since I've deleted that post it now just shows a 404.

My pre get posts function:

    function query_business_challenges( $query ) {

        if ( ! is_admin() && $query->is_main_query() && is_page('business-challenges')) {
            $query->set( 'post_type', 'business-challenges' );
        } // end if
    add_action( 'pre_get_posts', 'query_business_challenges', 1 );

And my Custom Post Type:

    function pt_business_challenges() {
        $labels = array(
            'name'                => 'Business Challenges',                        
            'singular_name'       => 'Business Challenge',                         
            'menu_name'           => 'B. Challenges',                        
            'parent_item_colon'   => 'Business Challenges',                        
            'all_items'           => 'All Business Challenges',                    
            'view_item'           => 'View Business Challenge',                    
            'add_new_item'        => 'Add New Business Challenge',                 
            'add_new'             => 'Add New',
            'edit_item'           => 'Edit Business Challenge',                    
            'update_item'         => 'Update Business Challenge',                  
            'search_items'        => 'Search Business Challenges',                 
            'not_found'           => 'Not found',
            'not_found_in_trash'  => 'Not found in Trash',
        $args = array(
            'label'               => 'business-challenges',                         
            'description'         => 'For New and Previous Business Challenges',   
            'labels'              => $labels,
            'supports'            => array( 'title', 'editor', 'excerpt', 'thumbnail', 'revisions', 'custom-fields', ),
            'hierarchical'        => false,
            'public'              => true,
            'show_ui'             => true,
            'show_in_menu'        => true,
            'rewrite' => array( 'slug' => '/business-challenges'),                  
            'show_in_nav_menus'   => true,
            'show_in_admin_bar'   => true,
            'menu_position'       => 7,
            'menu_icon'           => 'dashicons-chart-area',         
            'can_export'          => true,
            'has_archive'         => true,
            'exclude_from_search' => false,
            'publicly_queryable'  => true,
            'capability_type'     => 'page',
        register_post_type( 'business-challenges', $args );                         
    add_action( 'init', 'pt_business_challenges', 0 );

What am I doing wrong?

1 Answer 1


pre_get_posts does not work on page templates and static front pages. It will 404. If I read the WP_Query class correctly, the page ID is passed to a parameter such as p once the URL is parsed. You can try unsetting this parameter and check if it changes the query, but I doubt if this will be the only parameter to change to make it work. Have never played around with this, so everything is just pure speculation. This is quite an opportunity for someone to play around with pre_get_posts on page templates

You have to use a custom query here to output what you need. As for pagination, you need to add the following your custom query to make it work

This goes before you define your arguments

$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;

Remember to change 'paged' to 'page' for static front pages

You then need to set the 'paged' parameter in your query arguments

'paged' => $paged,

It is as easy then as to pass the $max_num_pages property of your custom query to your pagination function.


If your custom query looks like this

$q = new WP_Query( $args );

then you need to pass $q->max_num_pages to your pagination function like the following

next_posts_link( 'Next posts', $q->max_num_pages );


Just one or two notes on your code

  • If you want to show custom post types on page templates, you need to set has_archive to false, otherwise the archive template will be used to show custom post types

  • If you are talking about getting 404 errors on your custom post type archive template, then you just need to flush your permalinks by visiting the permalink settings page is backend. No need for any type of custom code or filters.


From your paste (which should be an edit to your question), you have a few small issues here

  • wp_reset_query() is wrong. It is used with query_posts which you should never use. You should be using wp_reset_postdata()

  • It seems you are trying to add your pagination on top of your query. In order for this to work, you need to define your custom query first. You can add your pagination before the loop however.

  • As I said, you need to set the $max_pages parameter in next_posts_link()

Your query should look similar to this

$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$args = array(
    'paged' => $paged,
    //Rest of your arguments
$loop = new WP_Query( $args );

 * If you need your pagination above the loop,
 * this is the earliest to add it. You cannot add it above
next_posts_link( 'Next Posts', $loop->max_num_pages );
previous_posts_link( 'Previous Posts' );

if ( $loop->have_posts() ) {
    while ( $loop->have_posts() ) {

        //YOUR LOOP

    } // endwhile

    // Add pagination here
    next_posts_link( 'Next Posts', $loop->max_num_pages );
    previous_posts_link( 'Previous Posts' );
    // Reset postdata, VERY VERY IMPORTANT
} // endif
  • I have made an edit to my post. Be sure to check it out :-) Commented Jun 23, 2015 at 11:38
  • Ah, I had no idea it didn't work on pages with custom wp queries... I've tried to do the $paged thing but it just 404's on the second page (always have trouble here, that's why I tried to keep to default query, where it works fine.). However, when I said pagination, what I really meant was <?php echo get_next_posts_page_link(); ?>. A link to next page of posts.
    – evu
    Commented Jun 23, 2015 at 13:21
  • No, you should use next_posts_link() or get_next_posts_link() and previous_posts_link()` or get_previous_posts_link() :-) Commented Jun 23, 2015 at 13:24
  • Using get_next_posts_link() gives a link with no /page/2, just the current page. get_next_posts_page_link() does give me /page/2 but it 404's. Pagination is the main thing that holds me up every time I do a Wordpress site :/ I need to build filtering into this yet... ED: pastebin.com/Ww9KgsnS if it helps ED2: I tried both page and paged.
    – evu
    Commented Jun 23, 2015 at 13:32
  • File an edit to your question with your code Commented Jun 23, 2015 at 13:44

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.