Ran into an interesting problem when importing a feature module that includes search api during a profile install. The install runs correctly up to filling out the site information form, but then I receive the below error after submitting the form. It's obviously occurring when the cron job is running:

( ! ) Fatal error: __clone method called on non-object in E:\Work\drupal\public_html\profiles\bir_profile\modules\contrib\search_api\search_api.module on line 1044
Call Stack
# Time      Memory           Function                         Location
1 0.0009    341704    {main}( )                               ..\install.php:0
2 0.0013    342032    install_drupal( )                       ..\install.php:26
3 0.2824    683992    install_run_tasks( )                    ..\install.core.inc:77
4 24.8736   69354656  install_run_task( )                     ..\install.core.inc:339
5 24.8736   69354656  install_finished( )                     ..\install.core.inc:470
6 30.5987   70148936  drupal_cron_run( )                      ..\install.core.inc:1527
7 38.2370   69987728  _search_api_indexing_queue_process( )   ..\common.inc:5243
8 38.2950   70017992  search_api_index_specific_items( )      ..\search_api.module:2142

I tracked it down to the foreach loop in the search_api_index_specific_items() function

foreach ($items as $id => $item) {
    $cloned_items[$id] = clone $item;
}

During the features import, some static node pages (nids 1 through 72) are added to the node table. The "$items" contain these nodes. However, the last node (nid = 72) is empty. I found this out by running the install profile again, printing out the $id and $item in the above loop before it is cloned. All the nodes in the database print out except nid 72. I see the 72 printed out, but no object data. Which makes sense since it throws the error. There is nothing different about node 72 in the database, as it is a static page much like the others.

As an experiment, I checked for $item being an object before cloning:

foreach ($items as $id => $item) {
    if (is_object($item) {
      $cloned_items[$id] = clone $item;
    }
}

The install profile worked without any errors doing this. So I then checked the index status in the newly installed site:
About 98% of all items have been indexed in their latest version (71 / 72).
Again, makes sense given I'm bypassing the empty node object with the above object check.

What does not make sense is why those nodes are being indexed. My index is filtered by bundle type:
Enabled data alterations
Bundle filter checked
Exclude items from indexing based on their bundle (content type, vocabulary, …).
.....
In the callback settings from the same page, I have "Only those from the selected bundles" selected, with only the bundles I want indexed (pages, book, and news not being any of them). If I clear the index and re-index via the Status page, all 72 nodes are indexed.

Questions:
So why are these nodes being indexed when they shouldn't? Or am I misreading the "Enabled data alterations" setting and what it does?
How can I figure out why nid 72 is empty during the profile install?
Perhaps Search API can't be included in Feature export?
Is it a good idea to check for "$item" being an object before attempting to clone, adding a watchdog in an "else" so an admin is at least warned, but the process does not fail?

Any suggestions would be appreciated.

Comments

mpv’s picture

Version: 7.x-1.4 » 7.x-1.7
Category: support » bug
Status: Active » Needs review
StatusFileSize
new557 bytes
new557 bytes

Thank you! I had the same error on 7.x-1.7 but your code fixed it. I've made it into a patch against 7.x-1.7 and 7.x-1.x-dev. I don't know if this is a fix or a dirty workaround, but it's working for me.

drunken monkey’s picture

Version: 7.x-1.7 » 7.x-1.x-dev
Component: Miscellaneous » Framework

What does not make sense is why those nodes are being indexed. My index is filtered by bundle type:

For determining the bundle, and thus whether the node should be included, the node has still got to be loaded beforehand. See #1184610: Limit indexes to specific entity bundles for a discussion about possibly changing this.

Regarding the issue itself, I'm a bit baffled as to what could cause this behavior – but I guess a lot of weird stuff happens during installation. If it's easily possible, could you maybe find out what $item is when it isn't an object, and what it contains (if anything)? Maybe that will lead us to the root of the problem.
Having said that, though, I don't have any objection to committing this workaround/fix either. It's trivial enough, after all, and if it helps a few users …

So, just waiting for a response on the debugging request, then I think we can just commit this.

In any case, thanks for reporting this issue and providing a fix right with it!

mpv’s picture

The first time search_api_index_specific_items is called during install I have

  $ids = array(0 => "1");

and the second time

  $ids = array(1 => "1");

In both cases $object is int(1).

Node 1 is a webform exported in a feature with uuid. Im using search_api_db as the backend.

Hope it helps.

drunken monkey’s picture

OK, thanks. That practically means there is a bug in another module (either Webform or UUID or whatever), since an entity_load() should never return just the ID – either a successfully loaded object or nothing at all. Whatever substitutes the node entity controller (or does some weird things in a load hook) has to be buggy.
(The backend shouldn't play any role here.)

Still, we should probably commit this little fix in any case, and maybe someone finds the time to debug this further and create an issue in the appropriate queue. (Basically, just find a custom node entity controller implementation in one of your modules, or a complex hook_node_load().)

mpv’s picture

Status: Needs review » Reviewed & tested by the community

I agree. Even if the module that is causing this error is fixed it's safer to have the check I think. Changing to RTBC.

Thanks for taking the time to review this.

drunken monkey’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new1.13 KB

No problem.
The patch lacked a watchdog() call in the error case, though, and a bit of explanation.
Revised patch attached, please also test/review!

mpv’s picture

Status: Needs review » Reviewed & tested by the community

Your last patch worked great, so changing to RTBC. The installation ended without errors and the message was added to the log.

Error during indexing: invalid item loaded for Node with ID 1.
drunken monkey’s picture

Status: Reviewed & tested by the community » Fixed

Excellent, good to hear.
Committed. Thanks again!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.