Custom post type archive – error in nav-menu-template.php

print_r($queried_object) right before line 439 generates the following – there’s no ‘ancestors’ key:

When you are on a post type archive calling get_queried_object (which the code probably does) or using WP_Query::$queried_object return the post type “object”. All that is is the arguments with which the post type was registered.

The relevant bit of nav-menu-template.php in WordPress 3.6.

<?php
function _wp_menu_item_classes_by_context( &$menu_items ) {
    // ...
    foreach ( (array) $menu_items as $key => $parent_item ) {
        // ...
        if (
            isset( $parent_item->type ) &&
            (
                // ancestral post object
                (
                    'post_type' == $parent_item->type &&
                    ! empty( $queried_object->post_type ) &&
                    is_post_type_hierarchical( $queried_object->post_type ) &&
                    in_array( $parent_item->object_id, $queried_object->ancestors ) &&
                    $parent_item->object != $queried_object->ID
                ) ||

                // ancestral term
                (
                    'taxonomy' == $parent_item->type &&
                    isset( $possible_taxonomy_ancestors[ $parent_item->object ] ) &&
                    in_array( $parent_item->object_id, $possible_taxonomy_ancestors[ $parent_item->object ] ) &&
                    (
                        ! isset( $queried_object->term_id ) ||
                        $parent_item->object_id != $queried_object->term_id
                    )
                )
            )
        ) {
            $classes[] = empty( $queried_object->taxonomy ) ? 'current-' . $queried_object->post_type . '-ancestor' : 'current-' . $queried_object->taxonomy . '-ancestor';
        }
        // ...
    }
    // ...
}

This bit ! empty( $queried_object->post_type ) should evaluate to false on post type archives. Something is adding post type to the queried object. And by something I mean your plugin which is _doing_it_wrong. Take a look at CCTM::register_custom_post_types() and CCTM::$default_post_type_def.

Anything that get’s passed into register_post_type is just stored as an argument in the post type globals array.

If I do this:

register_post_type('some_type', array('this_is_not_a_wp_arg' => true));

On archive-some_type.php I can check for this_is_not_a_wp_arg.

<?php
// archive-some_type.php
var_dump(get_queried_object()->this_is_not_a_wp_arg); // true

Because your plugin happens to put post_type into the arguments array, it causes WP to evaluate ! empty( $queried_object->post_type ) as true. This isn’t an issue in archive.php because $query_object->post_type is empty. As it should be on any post type archive. Unfortunately the CCTM plugin author doesn’t understand the consequences of passing a “reserved” word like post_type as an argument key. This is why prefixing things is important.

EDIT

A very hackish fix is to hook into init very late and loop through all the post types. If the post_type argument is set, remove it. This may break other things the plugin does in the admin area.

<?php
add_action('init', 'wpse115604_fix', 10000);
function wpse115604_fix()
{
   foreach (get_post_types(array(), 'objects') as $type) {
       if (isset($type->post_type)) {
           unset($type->post_type);
       }
   }
}

This would prevent you from having to edit the plugin itself. I would do the above, then report the issue to the plugin author. If/when it gets fixed in a future version, you’ll be able to remove that code.

TL;DR: CCTM adds a key to registered post types named post_type is messes with the order of things and sets a sequence of errors in motion.