Single template for custom post type doesn't work

I was reading a lot of posts about it, but I can’t find what I’m missing.

I have a CPT called “book”:
register_post_type( 'book', $args_books );

I have a default single.php file:
<?php get_template_part('templates/content-single', get_post_type()); ?>

I have a templates/content-single-book.php file:

    $clases = array(

<?php while (have_posts()) : the_post(); ?>
  <article <?php post_class($clases); ?>>
      <h1 class="entry-title"><?php the_title(); ?></h1>
      <?php the_content(); ?>
      <?php wp_link_pages(['before' => '<nav class="page-nav"><p>' . __('Pages:', 'sage'), 'after' => '</p></nav>']); ?>
    <?php comments_template('/templates/comments.php'); ?>
<?php endwhile; ?>

I have a page books created and its page-books.php template to show a list of books (it works).

But, when I try to show the single page of a book, I get a 404. Roots wrapper toolbar shows me Main: 404.php and Base: base.php

Why I can’t reach my templates/content-single-book.php? Thank you in advance.

Just for trying, but not strictly necessary, I tryed a base-book.php and single-book.php. None of them was used by WP.

Forget this thread, please. Same config works fine in a new sage theme.

Do you mind posting the resolution, assuming you figured it out?

Temporary issues with CPTs are usually to down to not flushing permalinks.

I have no resolution yet. Just I plan to rebuild theme from a new Sage installation to see what happens (I tryed to flush permalinks, it does not work). I’ll post here my research.

I got it! The problem was a function I have for sort records by custom field:

function my_pre_get_posts( $query ) {
    if( is_admin() ) {
        return $query;
  if ( $query->is_main_query() && !is_page()) {
    $query->set('orderby', 'meta_value');
    $query->set('meta_key', 'production_date');
    $query->set('order', 'DESC');
    return $query;
add_action('pre_get_posts', 'my_pre_get_posts');

So, WP was trying to sort results by a field that does not exist for that post type.

Adding && !is_single() was fixed:

if ( $query->is_main_query() && !is_page() && !is_single() ) {



Thanks for following up. It makes running forums like this so much easier.

1 Like