Repairs & sync
Everything that changes the index goes through Craft’s own indexer, so what lands in the table is exactly what a save would have written.
The one rule
Holmes never writes to searchindex itself. Reindexing calls Craft’s indexElementAttributes() or pushes Craft’s own UpdateSearchIndex job. The only rows Holmes deletes directly are ones whose element no longer exists, which is the one case Craft cannot handle for you — there is no element left to reindex.
This matters more than it sounds. A repair tool that writes its own keywords is a second implementation of Craft’s indexer, and the day it drifts is the day its reports become fiction.
Reindexing
Four scopes, smallest first:
| Scope | When |
|---|---|
| One element | Straight from a finding, or from an element’s detail view |
| A source | A section, volume or group — after adding a field to one layout |
| A site | After a site was added, or imported into |
| Everything | After a migration, or when you have lost confidence in the lot |
Reindexing from the control panel is queued by default, because reindexing anything larger than a handful of elements will outlast a web request. Set queueReindexing to false to run it in the request instead — sensible only on a small site or a local install.
Sources are Craft’s own
The list of sources comes from the element index sidebars — the same list the control panel builds for entries, assets, categories and everything else. Holmes does not maintain its own map of element types to sources, so an element type from another plugin appears with no special handling, as long as it provides sources the normal way.
One job per site
Craft’s UpdateSearchIndex job takes a single site ID or '*', never a list, so reindexing across several named sites means several jobs. That is expected, not a bug — you will see one queue job per site in the queue.
Deleting orphaned rows
Rows whose element no longer exists in that site can only be deleted; there is nothing to reindex. Holmes uses the same definition Craft does — no elements_sites row — which means trashed elements are not orphans. Craft keeps their index rows on purpose so a restore brings the element back searchable, and Holmes reports the count as a notice rather than removing them.
The deferred index queue
Craft 5.7 and later defer some reindexing into searchindexqueue rather than doing it in the request. Two things can go wrong with it, and Holmes handles both:
A backlog
Rows waiting to be processed mean the index is behind the content right now. Draining the queue works through them via Craft’s indexer. On a busy site a moving backlog is normal and needs nothing.
Rows a dead worker still claims
When a worker takes a batch it marks those rows reserved. If the worker dies — a deploy mid-job, an OOM kill, a timeout — the reservation is never released, and Craft’s own indexer will skip those rows forever. There is no interface in Craft for clearing them.
Holmes releases reserved rows before draining. If you have a reserved count that has not moved in days, that is what it is, and this is the fix.
A note for anyone writing similar code:
searchindexqueuehas nodateUpdatedcolumn, so updating it needs Craft’sDb::update()with timestamp updating switched off, or the query fails.
Fixing from a report
Findings that can be repaired carry a fix, applied one at a time or in bulk per check. Bulk fixes rediscover their own scope rather than working from the stored report — a report is a snapshot, and by the time someone clicks the button half of it may be stale. So a capped list never means a partial repair, and re-running a fix on an already-clean index does nothing.
Guarding repairs on production
Sync::EVENT_BEFORE_SYNC is cancellable, which is the seam for “nobody reindexes the whole site from the control panel on production”. See Extending for the handler.
From the console
# what sources exist, and their UIDs
php craft holmes/sync/sources
# one source
php craft holmes/sync/reindex --element-type='craft\elements\Entry' --source=section:<uid>
# everything
php craft holmes/sync/all
# delete rows whose element is gone
php craft holmes/sync/orphans
# release stuck reservations, then work off the backlog
php craft holmes/sync/queue