WordPress is 404ing all of my Custom Post Type posts. Have I missed a step here?

I’m using the following to set up my CPT:

function custom_post_types() {  
      'labels' => array(
        'name' => _x('Works', 'post type general name'),
        'singular_name' => _x('Work', 'post type singular name'),
        'add_new' => _x('Add New', 'Work'),
        'add_new_item' => __('Add New Work'),
        'edit_item' => __('Edit Work'),
        'new_item' => __('New Work'),
        'all_items' => __('All Works'),
        'view_item' => __('View Work'),
        'search_items' => __('Search Works'),
        'not_found' =>  __('No Works found'),
        'not_found_in_trash' => __('No Works found in Trash'), 
        'parent_item_colon' => '',
        'menu_name' => __('Works')
      'public' => true,
      'menu_position' => 5,
      //'rewrite' => array('slug' => 'work'),
      'supports' => array('title', 'editor', 'thumbnail'),
      'has_archive' => 'true'

add_action( 'init', 'custom_post_types' );

I originally had an underscore in the type (creative_work), rewriting the slug to just be “work”, but I had no idea which permutation WordPress would use to find the template—I tried file names like single-creative_work.php, single-creativework.php, single-work.php, all under themes/roots/ (I was using Roots as a baseline theme), with the contents:

<?php get_template_part('templates/content', 'work'); ?>

But themes/roots/templates/content-work.php was never displayed. Instead it seemed that themes/roots/page.php was being served up? When I manually edited page.php to get_template_part('templates/content', 'work') as a test, it seemingly used the template I wanted but then it had the post ID or something wrong where it was displaying the homepage for ANYTHING under website.com/creativework/.

In an attempt to eliminate all possible conflicts, I deactivated Roots in favor of Twentythirteen, and disabled all plugins except one, the one I wrote to set up the CPT (code at the top). Now, whenever I hit website.com/creativework/ or website.com/creativework/post-title (following the permalink from “View Work” in the post editor, or in Search results), I get a 404 instead of the homepage, despite both single-creativework.php and archive-creativework.php existing under themes/twentythirteen.

EDIT: website.com/?creativework=post-title, however, works.

I am hopelessly confused by all this. What is the correct, foolproof way to set up a custom post type template, step-by-step? Ideally I want to know how to do this in Roots, but for now I will settle on just how to get it working at all.

  • 1
    have you flushed rewrite rules since adding the custom post type? – Milo Sep 10 '13 at 15:49
  • I have now. No luck. – Hugh Guiney Sep 10 '13 at 16:32
  • AHA, I had tried to use flush_rewrite_rules() on plugin activation/deactivation, but that didn’t seem to do anything. When I changed the permalink structure and saved it, then it worked! If you post this as an answer I will accept it. – Hugh Guiney Sep 10 '13 at 17:00

Got it. I had tried to use flush_rewrite_rules() on plugin activation/deactivation, as so:

function creativeworks_activate() {
  // register taxonomies/post types here

function creativeworks_deactivate() {

register_activation_hook( __FILE__, 'creativeworks_activate' );
register_deactivation_hook( __FILE__, 'creativeworks_deactivate' );

…but that didn’t seem to do anything. However, when I changed the site-wide permalink options arbitrarily and saved them, then the rewrite rules were flushed successfully, and my custom post type templates started working again.

Thonks to Milo for pointing me in the right direction.

  • having these sort of problems with roots zoo but refreshing permalinks via the admin or above works. – v3nt Apr 17 '14 at 14:28
  • THANK YOU for posting your solution. My problem was a little different (WP ignoring single-{post_slug}.php template. Resaved permalinks and all is well. – jdm2112 Jul 9 '14 at 4:52

You have an error in the arguments of register_post_type that can be causing problems in the frontend. This argument:

 'has_archive' => 'true'

Should be:

 'has_archive' => true

The correct filename for the single template of your custom post type (creative_work) is single-creative_work.php and should be in your theme folder. For example, if your theme is called "my_theme", the file single-creative_work.php should be in wp-content/themes/my_theme/single-creative_work.php. You can also include template files from differents locations using template_include() function.

The folder structure you are talking about is not the usual in Wordpress (roots/lib/, roots/templates/, etc). Are these folders from a plugin?

  • They are from the Roots theme. (roots.io). – Hugh Guiney Sep 10 '13 at 13:17
  • My answer is still valid, you should put template files like single-*.php in the top folder of the theme. The files inside the folder roost/templates are not really templates files, they are files with code that will be inserted into several templates (those files are template parts). – cybmeta Sep 10 '13 at 13:23
  • I already tried that though; as I said in the OP, creating roots/single-creative_work.php seems to have no effect. (roots/ is the theme folder.) I keep getting the homepage. – Hugh Guiney Sep 10 '13 at 13:46
  • So, you have a custom post type creative_work and the template file single-creative_work.php is not used if you put this file in the top level folder of your theme. Can you try to register the post type like creativework (without the _) and then use single-creativework.php? – cybmeta Sep 10 '13 at 13:56
  • I did that, even replacing all instances of "creative_work" with "creativework" in the database, and it still isn't displaying. On top of that, I deactivated the Roots theme (switching to Twentythirteen) and all plugins (except for my own "Creative Works" plugin, which just sets up the custom post type), and now, instead of seeing the homepage, I get 404s, both for website.com/creativework/ and website.com/creativework/title-of-post. I have single-creativework.php and archive-creativework.php under twentythirteen. – Hugh Guiney Sep 10 '13 at 15:22

I also use roots and I have a small workaround (not really pretty but for me it keeps things organized). In the root of the template directory there's a single.php. There you can put:

    get_template_part('templates/creativework', 'header');
    get_template_part('templates/creativework', 'main');

Then you'd put creativework-header.php and creativework-main.php in the templates directory. I use this method because I have several custom post types and this way I can use my own naming instead of having a lot of single-cptname.php files. I actually deleted all contents of single.php and put the above function (and some more for each post type) there. Next to that, I can include multiple template parts per custom post type (some have up to 5). This keeps my stuff way better organized!

PS, are you sure the name of your custom post type is creativework and not creative-work?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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