Undefined property: stdClass::$labels in general-template.php post_type_archive_title()

The question:

I’ve got a custom post type with a standard tag taxonomy added to it like so: 'taxonomies' => array('post_tag'). I’ve added some tags to some posts of this CPT which are display on the front-end with the template tag the_tags() and the links it generates have this format http://local.mysite.dev/tag/tag1/. When I click such a link a page without any posts is generated using the tag.php template, but if I add ?post_type=seron_mycpt to the end of the URL like so http://local.mysite.dev/tag/tag1/?post_type=seron_mycpt a page with the relevant posts is generated using the same template but this time I also get these lines added to debug.log:

PHP Notice:  Undefined property: stdClass::$labels in /...sitepath.../wp-includes/general-template.php on line 665
PHP Notice:  Trying to get property of non-object in /...sitepath.../wp-includes/general-template.php on line 665

These notices are produced when wp_title() is called in the header.php template. According to the rewrite rules the request is transformed into the query tag=tag1&post_type=seron_mycpt.

For debugging I put print_r(get_queried_object()); in header.php and got this:

MYSITEstdClass Object
 [term_id] => 27
 [name] => tag1
 [slug] => tag1
 [term_group] => 0
 [term_taxonomy_id] => 27
 [taxonomy] => post_tag
 [description] =>
 [parent] => 0
 [count] => 2

I think WP expects a CPT object with a labels property but gets this object instead which doesn’t have that property.

If I tag an ordinary post with the same tag, the same header.php and tag.php templates are used and that post is displayed when using the http://local.mysite.dev/tag/tag1/ URL, and in that case no PHP notices are produced in debug.log, although print_r(get_queried_object()) shows a very similar object. Maybe WP never reaches the notice-producing line in general-template.php.

I don’t understand what this object is and why it is passed instead of a CPT object. Could someone explain?

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

This is a bug (one that I’ve encountered before) and could do with a ticket in trac (since I never took the time to submit one!)

The trouble starts with requests that set multiple is_* query flags as true (specifically flags that represent objects, such as single posts, pages, and post type & term archives).

This is because there can only ever be one “queried object” (in your case it’s the term).

Now the reason wp_title() seems to throw a wobbly is down to another function it calls:

function post_type_archive_title( $prefix = '', $display = true ) {
    if ( ! is_post_type_archive() )

    $post_type_obj = get_queried_object();
    $title = apply_filters('post_type_archive_title', $post_type_obj->labels->name );

    if ( $display )
        echo $prefix . $title;
        return $title;

Since the is_post_type_archive flag is true, it assumes the queried object is a post type, and tries to access an undefined property of what is actually a term object.

Whether the fix is to open up the possibility of multiple queried objects, or to implement more rigourous checking of them, I’m not sure, but I’ll get it on trac & we’ll see what follows.

Update: To suppress the error (& possible others), “switch off” one of the flags:

add_action( 'parse_query', 'wpse_71157_parse_query' );
function wpse_71157_parse_query( $wp_query )
    if ( $wp_query->is_post_type_archive && $wp_query->is_tax )
        $wp_query->is_post_type_archive = false;

Method 2

Here is what I did. In my taxonomy archive template I was relying on is_post_type_archive() to output additional div tags.

add_action( 'parse_query', 'orb_parse_query' );

function orb_parse_query( $wp_query ) {  
    global $post_type_obj;

    if ( $wp_query->is_post_type_archive && $wp_query->is_tax ) {
        $post_type_obj = get_queried_object();

        if (empty($post_type_obj->labels)) {
            $post_type_obj->labels = new stdClass();
            $post_type_obj->labels->name = 'dev/hack to fix WordPress Bug';

Method 3

Thanks all for help. I used solution from lordspace and little modified it, to show the name of the current custom post type.

add_action( 'parse_query', 'orb_parse_query' );

function orb_parse_query( $wp_query ) {  
    global $post_type_obj;

    if ( $wp_query->is_post_type_archive && $wp_query->is_tax ) {
        $post_type_obj = get_queried_object();

        if (empty($post_type_obj->labels)) {
            $currentPostType = $wp_query->query['post_type'];
            $currentPostTypeName = get_post_type_object($currentPostType)->labels->name;
            $post_type_obj->labels = new stdClass();
            $post_type_obj->labels->name = $currentPostTypeName;

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment