I added search api to an existing drupal 8 website which already has content migrated from a wordpress website. I tried indexing with both drush sapi-i and drush cron, it indexed some pages but than it stopped with the error:

LogicException: Could not determine image width for 'public://images/test.bmp' using image style with ID: example_style. This image style can
not be used for a responsive image style mapping using the 'sizes' attribute. in _responsive_image_build_source_attributes() (line 429 ...

Couldn't index items. Check the logs for details.

Both cron job and indexing where blocked from that point on.

Obviously this is not a Search API error, viewing the content was not possible neither – so it needed to be fixed anyway. But in first place it would be helpful if the content which causes the error would be ignored on following indexing attempts. That way there would be the chance to get most part of the site indexed and it will prevent the cron job from being stuck forever (or until the error get's discovered). The developer can come back and check which items couldn't be indexed and fix the problems without interferences on the rest of the site. In second place it would be very helpful to somehow see which entities couldn't be indexed (successfully).

It would be very helpful having a list of entities which failed completely to be indexed or where some problems occurred, like in another case:

Warning: While indexing items on search index Default content index, 1 item(s) did not have a view mode configured for one or more "Rendered item" fields.

Currently in both cases the entity in question does not show up in the error log, so some debugging efforts are necessary to find it. Would it be possible to log the entity type and id at least in the case where a recoverable error/warning occurs?

I don't know the insights of indexing. But I thought it might be possible before processing an entity to log id and type "somewhere". If a new index run encounters this entity in the log it could be skipped, as obviously something bad happened. It would be great if that log could be accessed from the status page to be informed. Could that be implemented as an index pre-processor? That way it could be disabled on sites where it won't be necessary and may harm performance.

Issue fork search_api-2920943

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

osopolar created an issue. See original summary.

osopolar’s picture

drunken monkey’s picture

Thanks for opening this issue!
I agree, this does sound sensible in your scenario. However, in practice, there are several problems:

  • Normally/often, multiple items are indexed at once. Depending on where the exception is encountered, we have no way of knowing which item(s) is/are actually the cause (and should be skipped in the future).
  • Indexing can fail for any number of reasons, some of which are just temporary (e.g., Solr server can't be reached), and since we can never know the complete set of possibilities (a LogicException from the Responsive Image module?!?), we have no way of knowing whether a specific error will also occur the next time we attempt to index that item. (No matter where the exception is caught, really.) This would probably require a considerably more complex system to work with most cases, and not worsen matters in more scenarios than it helps.

In general, we just try to do the best error handling we can. E.g., when rendering an item doesn't work, we should probably just log a warning and not include the "rendered_item" field's value in the indexed item. No big deal, and far better than blocking the whole indexing process, of course. However, the rendering method doesn't actually document that it can throw any exceptions – which, unfortunately, is inconsistent in large parts of Core. So, we can't even know which methods (as long as they are outside of the Search API) could even throw exceptions, or which one. This, of course, makes it almost impossible to handle all such cases properly. I'd say that either the rendering code or the Responsive Image module are at fault here – probably the latter one, I'd guess.

However, to solve your specific problem in our module (and not wait for Core to do something about it), we could probably just catch all exceptions that are thrown from rendering in \Drupal\search_api\Plugin\search_api\processor\RenderedItem::addFieldValues() and just log an error message and otherwise ignore it. And yes, I guess including the item ID would make sense in such cases, thanks!

osopolar’s picture

Normally/often, multiple items are indexed at once.

Do you really mean "at once" or in a batch one item after another. Isn't it always an entity which gets indexed? What if SAPI adds the entity before it gets indexed to a list (maybe with a timestamp) and when it finishes it removes it from that list. New index-jobs will ignore items on that list, so other items could get indexed. After configurable time (i.e. 1 hour) SAPI could try again to index that entity by setting a fresh timestamp and increase the attempt counter. If it gets indexed (successfully), then the item will be removed from the list. If not the entity may be completely ignored after a certain (configurable amount) of attempts = blacklist. The List could be exposed to views, to help developers to find indexing problems. It's not required to know why an item couldn't be indexed, it would be just fine to know which item, developers should then be able to debug it separately.

Could that be implemented by the use of one (or two) index-plugins? One plugin with highest priority (add entities to list an skip blacklisted entities) and the other one with lowest priority (unlist indexed entities).

I remember once with drupal 6 core we had problems with input filters using preg_replace_callback together with large content (base64 encoded images), that way core search blocked the cron job once every couple of months until we where able to identify and fix the problem. A safeguard as described would have been very handy.

Thanks for the workaround, I think that could be helpful for others too. I finally was able to find the indexing problems I had until now.

drunken monkey’s picture

Do you really mean "at once" or in a batch one item after another.

Generally, items in an indexing batch are all handed to the various sub-steps (field value extraction, preprocessing, actual indexing on server) as one single array. So, if we want to identify an individual item that makes problems, it would have to be the job of each individual sub-system (processor plugin, backend plugin, etc.) to do that. A centralized solution in just the "framework" part of the module wouldn't be possible (except for field extraction).

Isn't it always an entity which gets indexed?

No, you can index any kind of data as long as you write a datasource plugin for it.

What if SAPI …

Yes, something like that is what I mean with “a considerably more complex system”. Something like this might make sense, but it's a major framework addition which requires both good planning and quite some work in implementation. So, it'll have to wait until I have the free time available for it.

Could that be implemented by the use of one (or two) index-plugins? One plugin with highest priority (add entities to list an skip blacklisted entities) and the other one with lowest priority (unlist indexed entities).

Only for the "preprocessing by enabled processor" step. You couldn't spot problems during field extraction (where your actual problem was) or server indexing this way.

Anyways, the attached patch would implement the improved error handling for the "Rendered item" processor. Please test/review!

For the other logged warning, which you quote in your IS, it doesn't really make sense to include the item IDs, since the problem is not with the items, but with the field configuration, which doesn't have values set for all datasources or bundles. But maybe we could rephrase the message to make that clearer? Suggestions?

After committing this, I'd say we just leave the issue open to tackle the larger problem – when I have a bit of time to spare for it.

drunken monkey’s picture

socialnicheguru’s picture

Status: Active » Needs review
socialnicheguru’s picture

This worked for me.
It was really great to be able to see the node that was having an issue
Does it work for entities as well?

  • drunken monkey committed 7abf793 on 8.x-1.x
    Issue #2920943 by drunken monkey: Fixed error handling for "Rendered...
drunken monkey’s picture

Status: Needs review » Fixed

Thanks a lot for reporting, good to hear it works for you!
Committed.
Yes, it will also work for all other kinds of entities, not just nodes.

Status: Fixed » Closed (fixed)

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

hernani made their first commit to this issue’s fork.

hernani’s picture

StatusFileSize
new1.23 KB

The problem still occurs in case there is an error coming from the rendering of the node which does not originate an exception. (PHP Error for instance).

Small fix to address those cases attached.

hernani’s picture

StatusFileSize
new1.23 KB

File with correct name format.

chewie’s picture

StatusFileSize
new762 bytes

Patch reroll.

borisson_’s picture

Status: Closed (fixed) » Needs review

Reopening the issue, this seems like good hardening of our error handling.

+++ b/src/Plugin/search_api/processor/RenderedItem.php
@@ -296,6 +296,11 @@
+        // In case it is not an exception (it is an error), just transforms

typo in transform

hernani’s picture

StatusFileSize
new761 bytes

Fixing the patch.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

I think this is a good idea, this should make the rest of our error handling more robust.

drunken monkey’s picture

Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

Are you sure this is still needed, and not just a duplicate of the (already fixed) #3252430: Catch exception on indexing using Search API and keep indexation continuing?
Seems this just needlessly casts the Throwable to an exception?