We several times encountered an issue with the entity_metadata_wrapper when we try to access a value. For example, this is the following code throwing the exception this time :

// Load the author (user entity) of the node.
$wrapper_author = entity_metadata_wrapper('user', $node->uid);

// Get the value of an additional field (noderef) on the user.
$expert_profile = $wrapper_author->field_expert_profile_link->value();

// Load the related node (node entity) related to the author.
$wrapper_expert_profile = entity_metadata_wrapper('node', $expert_profile);

// Load the title of the related node.
$title = $wrapper_expert_profile->title->value();

This last line throws an exception visible in logs "EntityMetadataWrapperException: Missing data values. in EntityMetadataWrapper->value() (line 83 of /var/www/workspace/Capgemini.com/docroot/sites/all/modules/contrib/entity/includes/entity.wrapper.inc)." and a white page is displayed.

We face the same exception when we try to index the node in apachesolr :
> drush core-cron
WD cron: EntityMetadataWrapperException: Missing data values. in EntityMetadataWrapper->value() (line 83 of [error]
/var/www/workspace/Capgemini.com/docroot/sites/all/modules/contrib/entity/includes/entity.wrapper.inc).

From my understanding, the exception occured because the noderef (field field_expert_profile_link) references a nid which doesn't exist anymore. The first solution (the one which doesn't require a patch in any contributed module) could be a test after the entity_metadata_wrapper function to test the result, but it would involve a lot of code (only 2 or 3 lines but repeated each time the entity_metadata_wrapper function is used). The second solution could be a patch of the nodereference module. I understand noderefence should clean the value of the noderef when the referenced node is deleted (as it's addressed by this issue https://drupal.org/node/1346696). The last solution could be a patch of the entity module. We are not sure throwing an exception without catching it is also the best approach as it causes issues visible in the front office.

For this reason, we choose to create a patch for the entity.wrapper.inc to make the exception catched and not only thrown. Basically, I updated the EntityValueWrapper and EntityListWrapper value() implementations by adding a try/catch. I also implemented a value() method for the EntityStructureWrapper. If the exception is thrown by the EntityMetadataWrapper value() method, I only catch it and return NULL.

Feel free to comment the analys and the patch if you think it's not the best approach or if the patch should be improved.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

vbouchet’s picture

hockey2112’s picture

You are my hero. After much pulling-out of my hair, your solution fixed my issue. Thank you!

vbouchet’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 1: entity_catch_exception-2122009-1.patch, failed testing.

vbouchet’s picture

This patch need to be updated for the last version.

hargobind’s picture

Version: 7.x-1.2 » 7.x-1.x-dev
Status: Needs work » Needs review
FileSize
3.65 KB

Patch rerolled against the latest version.

Status: Needs review » Needs work

The last submitted patch, 6: entity_catch_exception-2122009-6.patch, failed testing.

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 6: entity_catch_exception-2122009-6.patch, failed testing.

hargobind’s picture

I rewrote this patch because I needed to address a WSOD on my site as well, but now that I look more into the code, I don't think it's the best approach. Sure it prevents critical failures, but it doesn't actually address the primary problem that the referenced entity is missing. As you said yourself, "noderefence should clean the value of the noderef when the referenced node is deleted (as it's addressed by this issue #1346696: On deletion of node/user, references to it are not removed)".

A couple of points:

  1. Exceptions should really only be prevented on EntityListWrapper and EntityStructureWrapper since those are the places where we currently cannot depend on the integrity of referenced entities (until the issue above is fixed). Adding it to EntityValueWrapper opens a lot of doors to potentially sloppy coding where programmers might incorrectly reference non-valid properties.
  2. I think this patch should at least call watchdog() to log that there is a missing noderef which will give site admins a way to clean up their content.