Fix the_content() Not Working in a Custom Post Type Template

Quick Summary
- Wrap the single-{post_type}.php display code in the Loop with have_posts() and the_post(), so the_content() knows which post to print.
- Because the_content() prints its output and returns nothing, a wpautop() wrapper has no effect, and the content filters normally add paragraphs already.
- If the single page returns a 404 instead of empty content, re-save Settings > Permalinks to refresh the rewrite rules.
In a single-{post_type}.php template, such as single-book.php for a post type called book, the_content() can print nothing when you call it on its own. It relies on the post data that the_post() sets up, so it has to run inside the Loop.
The fix: wrap your template code in the Loop
Put the part of the template that displays the post inside this structure:
<?php if(have_posts()): while(have_posts()): the_post(); ?>
//your code for the content
<?php echo wpautop( the_content() ); ?>
<?php endwhile; endif;?>have_posts()checks that WordPress found a post for the current URL, andthe_post()makes it the current post, so template tags such asthe_content(),the_title()andthe_post_thumbnail()know what to show.- Replace the
//your code for the contentline with your own markup. It sits outside the PHP tags, so if you leave it in, it prints on the page as plain text. the_content()prints the content itself and returns nothing, so thewpautop()wrapper around it has no effect. Your paragraphs still appear, becausethe_content()runs the content filters, which normally includewpautop(). A plain<?php the_content(); ?>gives the same result.
If the single page shows a 404 error instead of an empty content area, the cause is different: re-save Settings > Permalinks to refresh the rewrite rules, as covered in fixing 404 errors on custom post type pages.
Related articles
- getting post content from an ACF Relationship field: why the_content() can’t take a post ID
- splitting a post into pages with wp_link_pages(): another template tag that needs the Loop

