CPT Template Not Showing – Getting 404

I’m developing a Custom Post Type plugin, which works fine in dev. Now that I’ve moved it to production, I’m getting a 404 when I try to display the template for the CPT.

So, two questions:

Read More

1- Is there some mechanism to determine the path WP took to get through the hierarchy?

2- Why wouldn’t it just give me the single or index page?

I’ve dumped $wp_query and a stacktrace at the end of the 404. Here’s part of what I found:

[query] => Array
    (
        [page] => 
        [pagename] => refletters/proximity
    )

[request] => SELECT   wp_posts.* FROM wp_posts  WHERE 1=1  AND (wp_posts.ID = '0') AND wp_posts.post_type = 'page'  ORDER BY wp_posts.post_date DESC 
[posts] => Array
    (
    )

[queried_object] => 
[queried_object_id] => 0

And the stack trace:

2013-04-27 22:16:41 - 24.52.197.40 - TRACE - index.php - 404.php[39] - 
    wordpress/wp-content/themes/notoriousconsultant/404.php[39] - aaLog->logtrace
    wordpress/wp-includes/template-loader.php[50] - include
    wordpress/wp-blog-header.php[16] - require_once
    wordpress/index.php[17] - require

Thanks for your help.

Related posts

Leave a Reply

1 comment

  1. Always flush the rewrite rules when you register a new public post type or taxonomy. Otherwise the internal rewrite rules will not take that into account when an URL is mapped to a query.

    You can automate that process by hooking into registered_post_type and registered_taxonomy.

    Below is the updated code, based on feedback from comments and other people.

    Download as plugin T5 Silent Flush on GitHub.

    add_action( 'registered_post_type', 't5_silent_flush_cpt', 10, 2 );
    add_action( 'registered_taxonomy',  't5_silent_flush_tax', 10, 3 );
    
    /**
     * Flush rules for custom post types.
     *
     * @wp-hook registered_post_type
     * @param   string $post_type
     * @param   stdClass $args
     * @return  void
     */
    function t5_silent_flush_cpt( $post_type, $args )
    {
        if ( $args->_builtin )
            return;
    
        if ( ! $args->public )
            return;
    
        if ( ! $args->publicly_queryable )
            return;
    
        if ( ! $args->rewrite )
            return;
    
        $slug = $post_type;
    
        if ( isset ( $args->rewrite['slug'] ) && is_string( $args->rewrite['slug'] ) )
            $slug = $args->rewrite['slug'];
    
        $rules = get_option( 'rewrite_rules' );
    
        if ( ! isset ( $rules[ $slug . '/?$'] ) )
            flush_rewrite_rules( FALSE );
    }
    
    /**
     * Flush rules for custom post taxonomies.
     *
     * @wp-hook registered_taxonomy
     * @param   string $taxonomy
     * @param   string $object_type
     * @param   array  $args
     * @return  void
     */
    function t5_silent_flush_tax( $taxonomy, $object_type, $args )
    {
        // No idea why we get an array here, but an object for post types.
        // Objects are easier to write, so ...
        $args = (object) $args;
    
        if ( $args->_builtin )
            return;
    
        if ( ! $args->public )
            return;
    
        if ( ! $args->rewrite )
            return;
    
        $slug = $taxonomy;
    
        if ( isset ( $args->rewrite['slug'] ) && is_string( $args->rewrite['slug'] ) )
            $slug = $args->rewrite['slug'];
    
    
        $rules = get_option( 'rewrite_rules' );
    
        if ( ! isset ( $rules[ $slug . '/(.+?)/?$'] ) )
            flush_rewrite_rules( FALSE );
    }
    

    This will flush the rules each time you create a new post type or taxonomy. No need to visit the permalink settings again.