Problem/Motivation

The new search_api 1.18 Module introduced a very critical bug. Any change on an indexed node will lead to a fatal error if entities are indexed directly after node save.

Steps to reproduce

The issue only appears, if you have an index with mixed entity types. In our case we have an entity type "entity:commerce_product" and "entity:node" indexed in the same index.

Now we have a paragraph field on the "entity:node" index, but this field is not present on the "entity:commerce_product" type.

The error arises in search_api/src/Plugin/search_api/datasource/ContentEntity.php
Line 1062

      if (!$original_entity || !$items->equals($original_entity->get($relation_info['field_name']))) {
        $query = $this->entityTypeManager->getStorage($this->getEntityTypeId())
          ->getQuery();
        $query->accessCheck(FALSE);

The issue here is, that $this->getEntityTypeId() points to "entity:commerce_product" because it is the first datasource plugin. But on an index you can have multiple datasource plugins. The related field is only existing on the datasource plugin "entity:node" . This will result in a fatal error.

Proposed resolution

ContentEntity plugin should take into account that multiple different datasource plugins with different fields can exist

The current workaround is to revert to search_api 1.17 which works fine.

Comments

ayalon created an issue. See original summary.

ayalon’s picture

Issue summary: View changes
ayalon’s picture

Issue summary: View changes
Belialius’s picture

Can confirm that issue exists, have the same error on node save after the update to version 1.18.

kfritsche’s picture

We are running in the same issue. This happens for entity updates, delete and create actions.
This issue was introduced with 1.18 in #2007692: Changes in related entities don't lead to proper re-indexing

paulmckibben’s picture

Also seeing this issue on updating content with paragraphs. I can confirm that reverting search_api to version 1.17 resolves the issue.

ooziedie’s picture

I have the same issue as paulmckibben. Updating a node with paragraphs results in a fatal error. After downgrading to 1.17 everything works as expected.

drunken monkey’s picture

Status: Active » Postponed (maintainer needs more info)
Issue tags: +Needs tests

Sorry for not responding sooner. I have a lot of issues to look at, so unfortunately it sometimes takes longer. Thanks to mkalkbrenner for pointing this out to me! Fatal errors that occur for multiple people (especially in common scenarios like “saving a node”) are good candidates for pinging me on Slack, or even via mail, directly. (Just for the future.)

Anyways, unfortunately the issue description isn’t very helpful at the moment. I tried reproducing the problem, but it works fine for me. The “steps to reproduce” aren’t very clear, or detailed, though, so probably I just missed something.

Could someone try to come up with a minimal set of steps to reproduce, preferrably without unrelated contrib modules? Please also clearly state what action then leads to the fatal error. A stack trace would also be very helpful.
Furthermore, if you can get it, it would be very handy to know the values of $relation_info, $foreign_entity_relationship_map, $entity (at least the type) and $this->getPluginId().

A test reproducing the problem would, of course, be even more helpful – we’ll need one anyways, before committing, to ensure this doesn’t happen again in the future.

Finally, I hope at least some of you have also already tried the latest dev version?

drunken monkey’s picture

Component: General code » Framework
Status: Postponed (maintainer needs more info) » Needs review
Issue tags: +Needs change record
StatusFileSize
new4.01 KB

Tried reproducing by just adding the entity:user datasource to ReferencedEntitiesReindexingTest, but no luck.

However, I do see a problem in the reindexing logic, just by looking at the code. The foreign relationships map completely ignores the datasource plugin of a relationship. Maybe that is the problem? Please try out the attached patch (Edit: and make sure to clear the cache after applying it). (Answers to my questions in #8 would still be helpful, though.)

If we’d commit something like the attached patch, we should probably also create a change record, as the structure in the mapping_foreign_relationships event would (slightly) change.

drunken monkey’s picture

Status: Needs review » Postponed (maintainer needs more info)

Still need more info, just wanted to trigger the test bot.

cspitzlay’s picture

I tested the patch on top of search_api 1.18 with our setup and data.
It does seem to solve the issue.
No idea how to get to a minimal test case, yet.

Note to others testing the patch: Make sure you run drush cr after applying it.

cspitzlay’s picture

FWIW, here's a backtrace of the crash that happens with stock 1.18 when I delete one of our entities:
drush ev '\Drupal\my_metadata\Entity\MyMetadata::load(2405)->delete();'

Error: Call to a member function getColumns() on bool in Drupal\Core\Entity\Query\Sql\Tables->addField() (line 253 of /projectdir/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php) 
#0 /projectdir/core/lib/Drupal/Core/Entity/Query/Sql/Condition.php(52): Drupal\Core\Entity\Query\Sql\Tables->addField('field_metadata....', 'INNER', NULL)      
#1 /projectdir/core/lib/Drupal/Core/Entity/Query/Sql/Query.php(172): Drupal\Core\Entity\Query\Sql\Condition->compile(Object(Drupal\Core\Database\Driver\mysql\Select))                                    
#2 /projectdir/core/lib/Drupal/Core/Entity/Query/Sql/Query.php(80): Drupal\Core\Entity\Query\Sql\Query->compile()                                            
#3 /projectdir/modules/contrib/search_api/src/Plugin/search_api/datasource/ContentEntity.php(1074): Drupal\Core\Entity\Query\Sql\Query->execute()            
#4 /projectdir/modules/contrib/search_api/src/Utility/TrackingHelper.php(123):                                  
Drupal\search_api\Plugin\search_api\datasource\ContentEntity->getAffectedItemsForEntityChange(Object(Drupal\my_metadata\Entity\MyMetadata), Array, NULL)                                        
#5 /projectdir/modules/contrib/search_api/search_api.module(255): Drupal\search_api\Utility\TrackingHelper->trackReferencedEntityUpdate(Object(Drupal\my_metadata\Entity\MyMetadata), true)               
#6 [internal function]: search_api_entity_delete(Object(Drupal\my_metadata\Entity\MyMetadata))        
#7 /projectdir/core/lib/Drupal/Core/Extension/ModuleHandler.php(403): call_user_func_array('search_api_enti...', Array)                                      
#8 /projectdir/core/lib/Drupal/Core/Entity/EntityStorageBase.php(206): Drupal\Core\Extension\ModuleHandler->invokeAll('entity_delete', Array)                
#9 /projectdir/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(974): Drupal\Core\Entity\EntityStorageBase->invokeHook('delete', Object(Drupal\my_metadata\Entity\MyMetadata))                    
#10 /projectdir/core/lib/Drupal/Core/Entity/EntityStorageBase.php(457): Drupal\Core\Entity\ContentEntityStorageBase->invokeHook('delete', Object(Drupal\my_metadata\Entity\MyMetadata))                   
#11 /projectdir/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(809): Drupal\Core\Entity\EntityStorageBase->delete(Array)                        
#12 /projectdir/core/lib/Drupal/Core/Entity/EntityBase.php(418): Drupal\Core\Entity\Sql\SqlContentEntityStorage->delete(Array)                               
#13 /projectdir/vendor/drush/drush/src/Commands/core/PhpCommands.php(29) : eval()'d code(1): Drupal\Core\Entity\EntityBase->delete()                                
[... inside drush]
#28 @main.
drunken monkey’s picture

Status: Postponed (maintainer needs more info) » Needs work

Thanks a lot, cspitzlay! The stack trace already helps a lot! (Also very good to hear that my patch attempt worked for you.)

This makes it clear, though, that there is definitely also a Core bug involved. There should never just be a fatal error – that’s what exceptions are for. (And we make sure to catch all possible exceptions for that method call, specifically to make sure we don’t break saving entities.) After a quick search, I found the Core issue: #2893747: Unhelpful error message when an entity query contains an invalid field name. So definitely follow that, too.

Anyways, not running pointless entity queries (and breaking sites until the Core bug is fixed) is of course a good idea either way. So as soon as we can get a regression test for this (and maybe a bit more feedback about the fix), I can commit this.
For the test, it might already be sufficient to slightly alter the setup of ReferencedEntitiesReindexingTest, or maybe add another entity save operation.

drunken monkey’s picture

diegopino’s picture

Hi, we just discovered the same issue and was about to test the patch and I hit a different well know old issue.

ContentEntityTrackingManager::__construct() is expecting Drupal\Core\Entity\EntityTypeManager when it should be expecting an Interface. This breaks, e.g, web profiler... Should I open a different ISSUE for that, maybe it can be fixed In the same Patch? I feel it is a blocker.

Here
https://git.drupalcode.org/project/search_api/-/blob/8.x-1.18/src/Plugin...

ooziedie’s picture

@drunken monkey FYI: the backtrace for saving a node with paragraphs with vanilla 1.18.0:

Error: Call to a member function getColumns() on bool in Drupal\Core\Entity\Query\Sql\Tables->addField() (line 253 of /var/www/web/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php)
#0 /var/www/web/core/lib/Drupal/Core/Entity/Query/Sql/Condition.php(52): Drupal\Core\Entity\Query\Sql\Tables->addField()
#1 /var/www/web/core/lib/Drupal/Core/Entity/Query/Sql/Query.php(172): Drupal\Core\Entity\Query\Sql\Condition->compile()
#2 /var/www/web/core/lib/Drupal/Core/Entity/Query/Sql/Query.php(80): Drupal\Core\Entity\Query\Sql\Query->compile()
#3 /var/www/web/modules/contrib/search_api/src/Plugin/search_api/datasource/ContentEntity.php(1074): Drupal\Core\Entity\Query\Sql\Query->execute()
#4 /var/www/web/modules/contrib/search_api/src/Utility/TrackingHelper.php(123): Drupal\search_api\Plugin\search_api\datasource\ContentEntity->getAffectedItemsForEntityChange()
#5 /var/www/web/modules/contrib/search_api/search_api.module(230): Drupal\search_api\Utility\TrackingHelper->trackReferencedEntityUpdate()
#6 [internal function]: search_api_entity_update()
#7 /var/www/web/core/lib/Drupal/Core/Extension/ModuleHandler.php(403): call_user_func_array()
#8 /var/www/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(206): Drupal\Core\Extension\ModuleHandler->invokeAll()
#9 /var/www/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(843): Drupal\Core\Entity\EntityStorageBase->invokeHook()
#10 /var/www/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(535): Drupal\Core\Entity\ContentEntityStorageBase->invokeHook()
#11 /var/www/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(728): Drupal\Core\Entity\EntityStorageBase->doPostSave()
#12 /var/www/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(460): Drupal\Core\Entity\ContentEntityStorageBase->doPostSave()
#13 /var/www/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(837): Drupal\Core\Entity\EntityStorageBase->save()
#14 /var/www/web/core/lib/Drupal/Core/Entity/EntityBase.php(395): Drupal\Core\Entity\Sql\SqlContentEntityStorage->save()
#15 /var/www/web/modules/contrib/entity_reference_revisions/src/Plugin/Field/FieldType/EntityReferenceRevisionsItem.php(303): Drupal\Core\Entity\EntityBase->save()
#16 /var/www/web/core/lib/Drupal/Core/Field/FieldItemList.php(233): Drupal\entity_reference_revisions\Plugin\Field\FieldType\EntityReferenceRevisionsItem->preSave()
#17 /var/www/web/core/lib/Drupal/Core/Field/FieldItemList.php(191): Drupal\Core\Field\FieldItemList->delegateMethod()
#18 /var/www/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(881): Drupal\Core\Field\FieldItemList->preSave()
#19 /var/www/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(831): Drupal\Core\Entity\ContentEntityStorageBase->invokeFieldMethod()
#20 /var/www/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(500): Drupal\Core\Entity\ContentEntityStorageBase->invokeHook()
#21 /var/www/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(700): Drupal\Core\Entity\EntityStorageBase->doPreSave()
#22 /var/www/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(454): Drupal\Core\Entity\ContentEntityStorageBase->doPreSave()
#23 /var/www/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(837): Drupal\Core\Entity\EntityStorageBase->save()
#24 /var/www/web/core/lib/Drupal/Core/Entity/EntityBase.php(395): Drupal\Core\Entity\Sql\SqlContentEntityStorage->save()
#25 /var/www/web/core/modules/node/src/NodeForm.php(294): Drupal\Core\Entity\EntityBase->save()
#26 [internal function]: Drupal\node\NodeForm->save()
#27 /var/www/web/core/lib/Drupal/Core/Form/FormSubmitter.php(114): call_user_func_array()
#28 /var/www/web/core/lib/Drupal/Core/Form/FormSubmitter.php(52): Drupal\Core\Form\FormSubmitter->executeSubmitHandlers()
#29 /var/www/web/core/lib/Drupal/Core/Form/FormBuilder.php(593): Drupal\Core\Form\FormSubmitter->doSubmitForm()
#30 /var/www/web/core/lib/Drupal/Core/Form/FormBuilder.php(321): Drupal\Core\Form\FormBuilder->processForm()
#31 /var/www/web/core/lib/Drupal/Core/Controller/FormController.php(91): Drupal\Core\Form\FormBuilder->buildForm()
#32 [internal function]: Drupal\Core\Controller\FormController->getContentResult()
#33 /var/www/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array()
#34 /var/www/web/core/lib/Drupal/Core/Render/Renderer.php(573): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#35 /var/www/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext()
#36 /var/www/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext()
#37 /var/www/vendor/symfony/http-kernel/HttpKernel.php(151): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#38 /var/www/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
#39 /var/www/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle()
#40 /var/www/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle()
#41 /var/www/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#42 /var/www/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass()
#43 /var/www/web/modules/custom/***/src/StackMiddleware/***Headers.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle()
#44 /var/www/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\***\StackMiddleware\***Headers->handle()
#45 /var/www/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#46 /var/www/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#47 /var/www/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle()
#48 /var/www/web/index.php(25): Drupal\Core\DrupalKernel->handle()
#49 {main}.|

After installing the patch, saving a node with paragraphs works again.

cspitzlay’s picture

I didn't succeed to reproduce the issue with variations of ReferencedEntitiesReindexingTest.
So I decided to provide the debug dumps of the variable values in getAffectedItemsForEntityChange() just before things go awry.

$foreign_entity_relationship_map:

array (
  0 => 
  array (
    'entity_type' => 'kmm_link',
    'bundles' => 
    array (
    ),
    'property_path_to_foreign_entity' => 'link',
    'field_name' => 'uuid',
  ),
  1 => 
  array (
    'entity_type' => 'as_metadata',
    'bundles' => 
    array (
    ),
    'property_path_to_foreign_entity' => 'field_metadata:entity',
    'field_name' => 'uuid',
  ),
  2 => 
  array (
    'entity_type' => 'node',
    'bundles' => 
    array (
    ),
    'property_path_to_foreign_entity' => 'parameter',
    'field_name' => 'uuid',
  ),
  3 => 
  array (
    'entity_type' => 'node',
    'bundles' => 
    array (
    ),
    'property_path_to_foreign_entity' => 'parameter',
    'field_name' => 'type',
  ),
  4 => 
  array (
    'entity_type' => 'kmm_endpoint',
    'bundles' => 
    array (
    ),
    'property_path_to_foreign_entity' => 'endpoint',
    'field_name' => 'uuid',
  ),
  5 => 
  array (
    'entity_type' => 'kmm_link',
    'bundles' => 
    array (
      'link_bag' => 'link_bag',
    ),
    'property_path_to_foreign_entity' => 'field_link_bag',
    'field_name' => 'uuid',
  ),
)

$relation_info

array (
  'entity_type' => 'as_metadata',
  'bundles' => 
  array (
  ),
  'property_path_to_foreign_entity' => 'field_metadata:entity',
  'field_name' => 'uuid',
)

$this->getPluginId()
entity:kmm_endpoint

$this->getEntityTypeId()
kmm_endpoint

Here is the base field definition on as_metadata (the prefix 'field_' is there for historical reasons, it is indeed a base field). There is no such field on kmm_endpoint though.

    $fields['field_metadata'] = BaseFieldDefinition::create('entity_reference_inline')
      ->setLabel(t('More general metadata'))
      ->setDescription('')
      ->setTranslatable(FALSE)
      ->setRequired(FALSE)
      ->setCardinality(1)
      ->setSetting('target_type', 'as_metadata')
      ->setRevisionable(TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE);

Please note that things go wrong the second time the getAffectedItemsForEntityChange() is called.
The first time the plugin ID and entity type ID are entity:as_metadata and as_metadata, respectively.

drunken monkey’s picture

Version: 8.x-1.18 » 8.x-1.x-dev
Status: Needs work » Needs review
Issue tags: -Needs tests, -Needs change record
StatusFileSize
new3.68 KB
new3.03 KB
new7.43 KB

@ DiegoPino: That’s unrelated, so please create a new issue for it. (Unless there is one already.)

@ cspitzlay: Thanks a lot again for this important information! I now could confirm in manual testing that the key to triggering this bug is to have the trailing :entity included in the 'property_path_to_foreign_entity' key. I’m not sure why it’s there in some cases, but not in others, but by just adding that to the call I could now also reproduce this error – and was therefore able to write an automated test for it (see attached patch revision).

Also, I remembered that we are now free to use PHP 7, so it’s also actually possible to catch the fatal error even in this case. I’m not certain whether we should, as the problem should already be resolved by the rest of the changes, but it’s there as an option at least. (The danger is of masking other, actual fatal errors that maybe then get harder to debug, or could even cause data inconsistencies in some cases, I guess.)
I’d like some input/opinions from developers on that one, if possible.

Finally, I also created the change record – reviews are welcome for that, too.

The last submitted patch, 18: 3178941-18--referenced_entities_reindexing_fatal_error--tests_only.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

megachriz’s picture

  1. +++ b/src/Plugin/search_api/datasource/ContentEntity.php
    @@ -1073,7 +1078,8 @@ public function getAffectedItemsForEntityChange(EntityInterface $entity, array $
    -        catch (\Exception $e) {
    +        // @todo Switch back to \Exception once Core bug #2893747 is fixed.
    +        catch (\Throwable $e) {
               continue;
             }
    

    Maybe it would be good to document why any errors are catched, but not logged? Now it looks like that the code is fine with any errors that pop up during the process.

    Something like: "We are not interested in any SQL related errors."? (Though that still doesn't explain why SQL errors are ignored.)

    I'm trying to understand the implications of ignoring errors in this case. I think the consequence in this case is that entities may not be reindexed if a referenced entity changes. So when changing a term's name causes a SQL error when Search API tries to find entities in which that term is used, that error will be hidden. People may then notice that the old term name is used in the search results and would probably have a hard time figuring out how that could happen. So perhaps exceptions need to be logged. However, there can exist exceptions that are not necessarily errors (for example: MigrateSkipProcessException), so not sure how to properly filter these out as you cannot know all exception classes that exist in contrib modules.

  2. The change record seems to be missing a reference to an issue:

    As part of the fix for [#]

  3. There is a coding standard violation on the patch (see https://www.drupal.org/pift-ci-job/1880857)

For the tests only patch I checked if the error message showed up when commenting out 'datasource' => 'entity:node', and it did! So that's good.

I installed the patch on a site where I got the error on and I can confirm that the patch fixes the issue.

bakulahluwalia’s picture

Hi all,

I am facing the same error but with a different scenario.

Problem

Search api attachment configuration page throwing the WSOD when I click "Submit and test extraction" on "http://example.com/admin/config/search/search_api_attachments"

logs

Error: Call to a member function getColumns() on bool in Drupal\Core\Entity\Query\Sql\Tables->addField() (line 253 of /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php)
#0 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/Query/Sql/Condition.php(52): Drupal\Core\Entity\Query\Sql\Tables->addField('field_document....', 'INNER', NULL)
#1 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/Query/Sql/Query.php(172): Drupal\Core\Entity\Query\Sql\Condition->compile(Object(Drupal\Core\Database\Driver\mysql\Select))
#2 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/Query/Sql/Query.php(80): Drupal\Core\Entity\Query\Sql\Query->compile()
#3 /mnt/www/html/sitename/docroot/modules/contrib/search_api/src/Plugin/search_api/datasource/ContentEntity.php(1074): Drupal\Core\Entity\Query\Sql\Query->execute()
#4 /mnt/www/html/sitename/docroot/modules/contrib/search_api/src/Utility/TrackingHelper.php(123): Drupal\search_api\Plugin\search_api\datasource\ContentEntity->getAffectedItemsForEntityChange(Object(Drupal\file\Entity\File), Array, NULL)
#5 /mnt/www/html/sitename/docroot/modules/contrib/search_api/search_api.module(255): Drupal\search_api\Utility\TrackingHelper->trackReferencedEntityUpdate(Object(Drupal\file\Entity\File), true)
#6 [internal function]: search_api_entity_delete(Object(Drupal\file\Entity\File))
#7 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Extension/ModuleHandler.php(403): call_user_func_array('search_api_enti...', Array)
#8 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(206): Drupal\Core\Extension\ModuleHandler->invokeAll('entity_delete', Array)
#9 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(843): Drupal\Core\Entity\EntityStorageBase->invokeHook('delete', Object(Drupal\file\Entity\File))
#10 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(434): Drupal\Core\Entity\ContentEntityStorageBase->invokeHook('delete', Object(Drupal\file\Entity\File))
#11 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(786): Drupal\Core\Entity\EntityStorageBase->delete(Array)
#12 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Entity/EntityBase.php(403): Drupal\Core\Entity\Sql\SqlContentEntityStorage->delete(Array)
#13 /mnt/www/html/sitename/docroot/modules/contrib/search_api_attachments/src/Form/TextExtractorFormSettings.php(160): Drupal\Core\Entity\EntityBase->delete()
#14 [internal function]: Drupal\search_api_attachments\Form\TextExtractorFormSettings->submitForm(Array, Object(Drupal\Core\Form\FormState))
#15 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Form/FormSubmitter.php(114): call_user_func_array(Array, Array)
#16 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Form/FormSubmitter.php(52): Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object(Drupal\Core\Form\FormState))
#17 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Form/FormBuilder.php(593): Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object(Drupal\Core\Form\FormState))
#18 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Form/FormBuilder.php(321): Drupal\Core\Form\FormBuilder->processForm('search_api_atta...', Array, Object(Drupal\Core\Form\FormState))
#19 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Controller/FormController.php(91): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\search_api_attachments\Form\TextExtractorFormSettings), Object(Drupal\Core\Form\FormState))
#20 [internal function]: Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch))
#21 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#22 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/Render/Renderer.php(573): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#23 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#24 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#25 /mnt/www/html/sitename/vendor/symfony/http-kernel/HttpKernel.php(151): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#26 /mnt/www/html/sitename/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#27 /mnt/www/html/sitename/docroot/modules/contrib/simple_oauth/src/HttpMiddleware/BasicAuthSwap.php(67): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#28 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#30 /mnt/www/html/sitename/docroot/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#31 /mnt/www/html/sitename/docroot/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#32 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#33 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#34 /mnt/www/html/sitename/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#35 /mnt/www/html/sitename/docroot/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#36 /mnt/www/html/sitename/docroot/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#37 {main}

Is there any patch available that is working for search api attachment?

cspitzlay’s picture

@bakulahluwalia: Have you tried it with the patch from #18 and it did not work?

@drunken_monkey: As a developer I would prefer to let it crash in case of a fatal error instead of it going unnoticed or harder to debug.
Unless the reasons for "saving of entities on production must never be broken by indexing" are paramount (and trump index correctness on production) ...

bakulahluwalia’s picture

@cspitzlay, patch #18 worked for me.

Thanks @drunken_monkey for the patch.

Alice Heaton’s picture

Same issue, I can confirm patch on #18 fixes it. No side effects that I have seen so far.

drunken monkey’s picture

@ MegaChriz: Thanks a lot for the detailed review! I fixed all your notes – including adding logging for the caught exceptions. You’re right, doesn’t make sense to keep this quiet. Admins should at least be notified that something went wrong and that the index might be out of sync. (I guess I just omitted that initially because this was the default behavior before. But, of course, going forward it would be awesome if people could rely on this functionality.)

I also added logic to re-throw any \Throwables we don’t actually want to catch – i.e., just catch normal exceptions and this particular type of runtime error, and re-throw everything else. I think this should be a good balance, making it almost impossible that this hides any unrelated problems by accident.

@ cspitzlay: I can understand your reasoning (being a developer myself, I’d probably prefer it this way, too), but I do think most users would rather not have their website crash when saving an entity, at the price of a maybe slightly out-of-sync index (which they will now be notified about, and should be relatively easy to fix).

@ everyone: Thanks a lot for testing! Please also make sure that this new revision still works for you, then I think I’ll soon be able to commit it.

Anonymous’s picture

Hello, I have encountered the same issue and the patches from #18 and #25 both solve the issue for me. I would recommend using the patch from #25.

mjk73’s picture

We ran into this issue after updating to 8.9.10.

The patch in #25 resolved it. Thanks @drunken-monkey. :)

  • drunken monkey committed 04b0fcb on 8.x-1.x
    Issue #3178941 by drunken monkey, cspitzlay, MegaChriz, ooziedie,...
drunken monkey’s picture

Status: Needs review » Fixed

OK, great to hear, thanks a lot for testing.
Committed.
Thanks again, everyone!

Status: Fixed » Closed (fixed)

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

renrhaf’s picture

Hi ! Thanks a lot for this fix.
This patch cause an other issue in my case : the "logException" method expects an Exception object but receive now an Error object.
Maybe we should switch that to a Throwable entity.
Applying core patch https://www.drupal.org/project/drupal/issues/2893747#comment-13886822 fixed the issue for now.