Repository navigation
IndexQueueRepository::resetDispatchedItems() throws TypeError (string expected, int given) instead of resetting a failed batch dispatch #493
Description
Affected Version
2026.2
Affected capability
Core
Steps to reproduce
Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\QueueMessageService::handleMessage() reads the dispatch id straight from a raw-SQL result row:
// QueueMessageService.php:45-66
$dispatchId = $entries[0]['dispatched'] ?? null;
try {
$this->messageBus->dispatch(new IndexUpdateQueueMessage($entries));
} catch (Exception $exception) {
// ...
if ($dispatchId !== null) {
$this->indexQueueRepository->resetDispatchedItems($dispatchId);
}
break;
}$entries comes from IndexQueueRepository::getUnhandledIndexQueueEntries(), which for the dispatching branch runs a raw SELECT * ... WHERE dispatched = :dispatchId via Connection::executeQuery()->fetchAllAssociative() (IndexQueueRepository.php:92-107). The dispatched column value comes back as a native PHP int in this environment (consistent with how the id is produced: dispatchItems() returns int, built by generateDispatchId(int $timestamp): int, IndexQueueRepository.php:294-329).
resetDispatchedItems() is declared as:
// IndexQueueRepository.php:331
public function resetDispatchedItems(string $dispatchId): voidQueueMessageService.php has declare(strict_types=1) at the top of the file, so calling resetDispatchedItems($dispatchId) with the int from $entries[0]['dispatched'] throws a TypeError instead of resetting the batch.
Note this isn't an arbitrary type choice on resetDispatchedItems()'s part — the bundle's own entity already establishes string as the correct type for this field:
// Entity/IndexQueue.php:53, 129, 132
#[ORM\Column(type: 'bigint', options: ['unsigned' => true, 'default' => 0])]
private string $dispatched;
public function getDispatched(): string { return $this->dispatched; }
public function setDispatched(string $dispatched): void { $this->dispatched = $dispatched; }So dispatchItems()/generateDispatchId() returning/using int for the same logical value is what's inconsistent with the bundle's own data model, not resetDispatchedItems()'s string parameter — the raw executeQuery()->fetchAllAssociative() call in getUnhandledIndexQueueEntries() bypasses Doctrine's type conversion entirely, so the column comes back as the driver's native int instead of the entity's string.
This happens on any exception thrown while $this->messageBus->dispatch(new IndexUpdateQueueMessage($entries)) is executing for a non-empty batch.
Actual Behavior
The recovery path itself crashes with:
TypeError: Pimcore\Bundle\GenericDataIndexBundle\Repository\IndexQueueRepository::resetDispatchedItems(): Argument #1 ($dispatchId) must be of type string, int given, called in .../QueueMessageService.php on line 66
This propagates up through DispatchQueueMessagesHandler, and Symfony Messenger removes the DispatchQueueMessagesMessage from the transport after 0 retries (logged as critical). The affected index-queue rows are never reset to dispatched = 0, so they are not retried through the normal path — they only get picked up again via the unrelated 24h-staleness fallback already built into dispatchItems(). Net effect: a batch dispatch failure, which should be a graceful "reset and retry later," instead becomes an unhandled crash and up to a 24h delay before the affected elements are reindexed.
Expected Behavior
Since the entity already defines this field as string (see above), dispatchItems() / generateDispatchId() should produce a string dispatch id (or QueueMessageService::handleMessage() should cast $dispatchId to string before calling resetDispatchedItems()), so the raw-SQL dispatch path stays consistent with the bundle's own data model. Either way, a failed batch dispatch should end with the batch being reset for retry, not with an unrelated TypeError crashing the whole handler.
Metadata
Metadata
Assignees
Labels
Type
Fields
Platform Version
Affected capability
Galaxy
Activity
[Bug] Fix TypeError when resetting dispatched index queue items (#528)