The Linux Page

Taxonomy error generated from invalid nodes

Today I ran in an error that looked like this:

Invalid argument supplied for foreach() in <path>/modules/taxonomy/taxonomy.module on line 1214.

The line number may vary depending on the version you are using. At the time, I had Drupal 6.14 and the line number was 1214.

The problem is with a node that has an invalid definition of its taxonomy field. In other words, the $node->taxonomy is not defined. If it were an empty array, the function would not fail.

I was updating a new Drupal website from an old static website generating nodes automatically with a little module. There were a little over 300 such nodes. My first attempt did not include all the necessary taxonomy entries (Oops). I fixed a few of the nodes by hand, and then I decided that I should do that again with the taxonomy included. Somehow, when I deleted the remaining nodes, I missed one. Now, what is the most surprising is that I did not get any such errors when I edited the first few converted nodes...

Looking for a solution, I found several pages on Drupal.org that would explain that the problem came from a few invalid nodes. Edit them to fix them and when you click on Save you'll be all good to go. So... I started to look for the node.

First I put a var_dump($node) so I could see the content of the node at the time the failing function is called. I thought that at least that way I'd see the node identifier and know which node is generating this problem.

There is the function we are dealing with:

  function taxonomy_node_update_index(&$node) {
    $output = array();
    foreach ($node->taxonomy as $term) {
      $output[] = $term->name;
    }
    if (count($output)) {
      return '<strong>('. implode(', ', $output) .')</strong>';
    }
  }

I just added a test and a var_dump() at the beginning as follow:

    if (!is_array($node->taxonomy)) {
      var_dump($node);
    }

The output was quite interesting. That is, not quite what I anticipated. An Object, yes, but very limited. And it idid not even include the node identifier!

stdClass Object (
	[build_mode] => 2,
	[body] => <!-- google_ad_section_start --><!-- google_ad_section_end -->,
	[readmore] => ,
	[content] => Array (
		[adsense_start] => Array (
			[#weight] => -5,
			[#value] => <!-- google_ad_section_start -->,
			[#title] => ,
			[#description] => ,
			[#printed] => 1
		),
		[body] => Array (
			[#weight] => 0,
			[#value] => ,
			[#title] => ,
			[#description] => ,
			[#printed] => 1
		),
		[adsense_end] => Array (
			[#weight] => 5,
			[#value] => <!-- google_ad_section_end -->,
			[#title] => ,
			[#description] => ,
			[#printed] => 1
		),
		[#title] => ,
		[#description] => ,
		[#children] => <!-- google_ad_section_start --><!-- google_ad_section_end -->,
		[#printed] => 1
	)
)

 At that point I wondered how I could find the problem and decided that a trace of the stack would help much. So I changed my code to use a trace:

    if (!is_array($node->taxonomy)) {
      debug_print_backtrace();
    }

The debug call printed the stack so at least I could see who calls what. Quite instructive, although I still don't know what the update index event is used for, I can see that was the reason why the taxonomy function was being called.

The stack is a bit long because a three entries have the node object as a parameter. Notice that the nid does NOT appear in those! Yet, frame #3 gave me my answer. My bad node was number 239. Cool! So, now I could test that node.

#0  taxonomy_node_update_index(
  stdClass Object (
    [build_mode] => 2,
    [body] => <!-- google_ad_section_start --><!-- google_ad_section_end -->,
    [readmore] => ,
    [content] => Array (
      [adsense_start] => Array (
        [#weight] => -5,
        [#value] => <!-- google_ad_section_start -->,
        [#title] => ,[#description] => ,
        [#printed] => 1
      ),
      [body] => Array(
        [#weight] => 0,
        [#value] => ,
        [#title] => ,
        [#description] => ,
        [#printed] => 1
      ),
      [adsense_end] => Array (
        [#weight] => 5,
        [#value] => <!-- google_ad_section_end -->,
        [#title] => ,
        [#description] => ,
        [#printed] => 1
      ),
      [#title] => ,
      [#description] => ,
      [#children] => <!-- google_ad_section_start --><!-- google_ad_section_end -->,
      [#printed] => 1
    )
  )
) called at [/usr/clients/www/drupal/modules/taxonomy/taxonomy.module:1205]

#1  taxonomy_nodeapi(
  stdClass Object (
    [build_mode] => 2,
    [body] => <!-- google_ad_section_start --><!-- google_ad_section_end -->,
    [readmore] => ,
    [content] => Array (
      [adsense_start] => Array (
        [#weight] => -5,
	[#value] => <!-- google_ad_section_start -->,
	[#title] => ,
	[#description] => ,
	[#printed] => 1
      ),
      [body] => Array (
        [#weight] => 0,
	[#value] => ,
	[#title] => ,
	[#description] => ,
	[#printed] => 1
      ),
      [adsense_end] => Array (
        [#weight] => 5,
	[#value] => <!-- google_ad_section_end -->,
	[#title] => ,
	[#description] => ,
	[#printed] => 1
      ),
      [#title] => ,
      [#description] => ,
      [#children] => <!-- google_ad_section_start --><!-- google_ad_section_end -->,
      [#printed] => 1
    )
  ),
  update index,
  ,
) called at [/usr/clients/www/drupal/modules/node/node.module:673]

#2  node_invoke_nodeapi(
  stdClass Object (
    [build_mode] => 2,
    [body] => <!-- google_ad_section_start --><!-- google_ad_section_end -->,
    [readmore] => ,
    [content] => Array (
      [adsense_start] => Array (
        [#weight] => -5,
	[#value] => <!-- google_ad_section_start -->,
	[#title] => ,
	[#description] => ,
	[#printed] => 1
      ),
      [body] => Array (
        [#weight] => 0,
        [#value] => ,
	[#title] => ,
	[#description] => ,
	[#printed] => 1
      ),
      [adsense_end] => Array (
	[#weight] => 5,
	[#value] => <!-- google_ad_section_end -->,
	[#title] => ,
	[#description] => ,
	[#printed] => 1
      ),
      [#title] => ,
      [#description] => ,
      [#children] => <!-- google_ad_section_start --><!-- google_ad_section_end -->,
      [#printed] => 1
    )
  ),
  update index
) called at [/usr/clients/www/drupal/modules/node/node.module:1828]

#3  _node_index_node(stdClass Object ([nid] => 239))
    called at [/usr/clients/www/drupal/modules/node/node.module:1804]

#4  node_update_index()

#5  call_user_func_array(node_update_index, Array ())
    called at [/usr/clients/www/drupal/includes/module.inc:450]

#6  module_invoke(node, update_index)
    called at [/usr/clients/www/drupal/modules/search/search.module:273]

#7  search_cron()

#8  call_user_func_array(search_cron, Array ())
    called at [/usr/clients/www/drupal/includes/module.inc:471]

#9  module_invoke_all(cron) called at [/usr/clients/www/drupal/includes/common.inc:2693]

#10 drupal_cron_run() called at [/usr/clients/www/drupal/cron.php:11]

I wasn't too sure what to do with that node though... hmmm... when I tried to view the node it told me "Page not found". How weird! Then I tried to edit the node, same thing. I went to the administration area and tried to delete the node from the list. Did not work either!?

So I tested directly in the database and delete the two entries I found. One in the node table and the other in the node_comment_statistics. I'm really not too sure why that one node did not make it right. Out of the about 300 nodes I added today, this is the only one that failed.

In any event, once I delete those two entries, all the errors went away.