The checks

Ten checks ship with Holmes. Each answers one question about the index. Nine are pure SQL and run in every audit; one loads elements and only runs in a deep pass.

Every check has a handle, which is what --checks= and the disabledChecks setting take.

Unindexed elements

unindexed-elements · Critical · Every audit · Fix: Reindex

Finds. Elements that exist in a site but have no search index rows there at all.

Why it matters. They cannot be found by any search, however they are spelled. This is the single most common finding on a site that has ever been imported into.

Orphaned rows

orphaned-rows · Critical · Every audit · Fix: Delete rows

Finds. Index rows whose element no longer exists in that site.

Why it matters. Nothing will ever update or remove these on its own, and they make every search do more work than it needs to. Craft’s own definition of an orphan is a row with no elements_sites row, which deliberately does not include trashed elements.

Keyword drift

keyword-drift · Warning · Deep audits only · Fix: Reindex

Finds. Rows whose stored keywords disagree with the keywords Craft would write for that element right now.

Why it matters. The one thing set comparisons cannot see. If content changed without the index being told, every other check will call the index healthy.

Partly indexed elements

missing-field-rows · Warning · Every audit · Fix: Reindex

Finds. Elements missing an index row for a searchable field that is in their layout.

Why it matters. Usually a field added after the content was last saved. That field’s content cannot be searched on those elements, while it works perfectly on anything saved since — which makes it look like a search bug rather than an indexing one.

Stale field rows

stale-field-rows · Warning · Every audit · Fix: Delete rows

Finds. Index rows for fields that were deleted, made non-searchable, or removed from the element’s layout.

Why it matters. Craft leaves these behind, so content you have taken out of a field can still be found by searching for it. Occasionally a compliance problem, not just an untidy one.

Empty keywords

empty-keywords · Warning, or notice · Every audit · Fix: Reindex

Finds. Elements whose index rows all exist but are empty.

Why it matters. They look indexed and are impossible to find. Nested elements — Matrix blocks and the like — are reported as a notice instead, because their content is normally searchable through the element that owns them.

Revision rows

revision-rows · Warning · Every audit · Fix: Delete rows

Finds. Index rows belonging to element revisions.

Why it matters. Craft never indexes revisions, so these are always leftovers — and they can put an old version of an entry into search results.

Unknown attribute rows

unknown-attribute-rows · Warning · Every audit · Fix: Delete rows

Finds. Rows for element attributes the element type no longer says are searchable.

Why it matters. Left over from an older Craft, an uninstalled plugin, or a changed element type. They match searches for content that is no longer meant to be searchable.

Truncated keywords

truncated-keywords · Warning · Every audit · Fix: None — see below

Finds. Index rows sitting at the storage ceiling of the keywords column.

Why it matters. Craft cuts keywords off at the column’s capacity. Everything past the cut is unsearchable, silently — the row looks perfectly healthy. Long rich-text fields are the usual cause.

Pending index queue

queue-backlog · Notice, or warning · Every audit · Fix: Drain queue

Finds. Elements Craft has queued for reindexing but not yet processed, and rows a worker has reserved.

Why it matters. A backlog means the index is behind the content right now. Reserved rows that never clear mean a queue worker died holding the job, and Craft will skip those rows forever.

Two that need a word of explanation

Truncated keywords has no fix

Reindexing a truncated row produces the same truncated row — the content genuinely does not fit. The remedies are on your side: split the field, make the longest fields non-searchable, or raise the column’s capacity in the database. Holmes reports it because the failure is otherwise completely silent.

Pending index queue is usually not a fault

A backlog on a busy site is normal and clears itself. What is worth acting on is a reserved count that does not move: those rows are invisible to Craft’s indexer forever, because a dead worker’s claim is never released. Holmes releases them before draining. See Repairs & sync.

Turning checks off

A site can legitimately trip a check — a headless install with no titles, say, or a section whose entries are deliberately blank. Add the handle to disabledChecks in the settings and it never runs. To filter individual findings rather than lose the whole check, use the EVENT_DEFINE_ISSUES event described in Extending.

Adding your own

A check is one class and one event handler, and it can know how to repair its own findings in bulk. See Extending.