Calling clear from updateIndex in a BackendClient can result in an infinite pending task loop

Created on 27 August 2025, 15 days ago

Problem/Motivation

Certain search api backends like elasticsearch and opensearch require clearing the index if there are changes to field mappings. This requires calling clear in the updateIndex method of the BackendClient if mapping changes are detected. If a SearchApiException is thrown in the updateIndex method before clear is called, search api catches the exception and adds a pending task. When you go to execute the pending task, it tries to re-run updateIndex which then calls $index->clear() again. This then calls deleteAllIndexItems() on the server which again tries to run pending tasks for the server, which tries to run updateIndex again, which calls $index->clear() and so on...

The only way to fix is to manually delete the pending task.

Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'search_api.task.updateIndex') (Line: 212)
Drupal\search_api\Task\TaskManager->executeSpecificTask(Object) (Line: 264)
Drupal\search_api\Task\TaskManager->executeAllTasks(Array, 100) (Line: 95)
Drupal\search_api\Task\ServerTaskManager->execute(Object) (Line: 424)
Drupal\search_api\Entity\Server->deleteAllIndexItems(Object) (Line: 1222)
Drupal\search_api\Entity\Index->clear() (Line: 233)
Drupal\search_api_opensearch\SearchAPI\BackendClient->updateIndex(Object) (Line: 440)
Drupal\search_api_opensearch\Plugin\search_api\backend\OpenSearchBackend->updateIndex(Object) (Line: 160)
Drupal\search_api\Task\ServerTaskManager->executeTask(Object) (Line: 115)
Drupal\search_api\Task\ServerTaskManager->processEvent(Object, 'search_api.task.updateIndex', Object)
call_user_func(Array, Object, 'search_api.task.updateIndex', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'search_api.task.updateIndex') (Line: 212)
Drupal\search_api\Task\TaskManager->executeSpecificTask(Object) (Line: 264)
Drupal\search_api\Task\TaskManager->executeAllTasks(Array, 100) (Line: 95)
Drupal\search_api\Task\ServerTaskManager->execute(Object) (Line: 424)
Drupal\search_api\Entity\Server->deleteAllIndexItems(Object) (Line: 1222)
Drupal\search_api\Entity\Index->clear() (Line: 233)
Drupal\search_api_opensearch\SearchAPI\BackendClient->updateIndex(Object) (Line: 440)
Drupal\search_api_opensearch\Plugin\search_api\backend\OpenSearchBackend->updateIndex(Object) (Line: 160)
Drupal\search_api\Task\ServerTaskManager->executeTask(Object) (Line: 115)
Drupal\search_api\Task\ServerTaskManager->processEvent(Object, 'search_api.task.updateIndex', Object)
call_user_func(Array, Object, 'search_api.task.updateIndex', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'search_api.task.updateIndex') (Line: 212)
Drupal\search_api\Task\TaskManager->executeSpecificTask(Object) (Line: 362)
Drupal\search_api\Task\TaskManager->processBatch(Array, Array, Array) (Line: 297)

Steps to reproduce

  1. Throw a searchApiException in your backend client's updateIndex method.
  2. Remove the exception.
  3. The updateIndex method must have an $index->clear() method.
  4. Try "Execute pending tasks"
  5. You will get a loop.

Proposed resolution

The code that starts the pending task execution should remove the task from the list of pending tasks so that when $index->clear() is called again in updateIndex it doesn't try and run the pending task again.

Remaining tasks

N/A

🐛 Bug report
Status

Active

Version

1.0

Component

General code

Created by

achap 🇦🇺

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024