Configuration & operations
Rebuilding the Zebra index when Koha search results go stale
A record you can open by its number but cannot find by searching means the index is behind, not that the record is missing. Here is how to rebuild it properly.
Updated 2026-08-09 · Tested against Koha 26.05
If a record opens fine from its own URL but never appears in a search, Koha's Zebra index is out of date — the catalogue is intact and the search index is behind it. Rebuild with sudo koha-rebuild-zebra -f -v <instance>, then make sure the indexer daemon is running so it does not drift again.
A full rebuild is not instant
- Search is degraded while it runs. On a live catalogue, run it outside opening hours.
- Check free space first: the index is rebuilt, not patched, so both copies exist briefly.
- Circulation is unaffected — checkouts and returns do not go through Zebra.
Step 1Rebuild the index
$ sudo koha-rebuild-zebra -f -v library exporting bibliorecords exported: 218430zebraidx: 218430 recordsexporting authorityrecords exported: 41277Replace library with the instance name (sudo koha-list). The flags, from the script's own help:
| Flag | What it does |
|---|---|
| <code>-f</code>, <code>--full</code> | Full reindex of the whole collection. Without it the run is incremental and will not repair an index that has already drifted. |
| <code>-v</code> | Verbose. Use it — a silent run tells you nothing about whether it worked. |
| <code>-b</code> | Bibliographic records only. Much faster when authorities are fine. |
| <code>-a</code> | Authority records only. |
| <code>--force</code> | Run an incremental index even when the indexer daemon is enabled. |
| <code>-q</code> | Quiet — for scripts and cron, not for diagnosis. |
Narrow it before you widen it
-b reindexes bibliographic records alone and finishes in a fraction of the time. Reach for the full rebuild when the targeted one does not fix it.Step 2Find out why it fell behind
A rebuild fixes today. It does not fix the reason, and if you stop here you will be running it again next month. Koha keeps the index current in one of two ways, and exactly one of them should be active.
The indexer daemon watches the queue and indexes changes as they happen. This is the normal arrangement:
$ sudo koha-indexer --status library$ systemctl status koha-indexer@libraryNot running? Start it and enable it so it survives a reboot:
$ sudo koha-indexer --start library$ sudo systemctl enable koha-indexer@libraryThe cron fallback is a scheduled incremental index every five minutes, used on installs that do not run the daemon. It ships commented out in /etc/cron.d/koha-common and looks like this:
*/5 * * * * root test -x /usr/sbin/koha-rebuild-zebra && \ koha-rebuild-zebra -q $(koha-list --enabled)One or the other, never both
Step 3Verify it actually worked
Do not verify by searching for something you already believe is indexed. Compare the catalogue against the index directly:
$ sudo koha-mysql library -e "SELECT COUNT(*) FROM biblio;" 218430Then run a blank search in the OPAC — an empty query returns everything indexed. The two numbers should be close. A large gap means the rebuild did not complete, and the reason will be in the log:
$ sudo tail -50 /var/log/koha/library/zebra-error.logWhy there is a separate index at all
A MARC record is not a row of columns; it is a nested structure with repeatable fields and subfields, and searching it the way a catalogue user expects — a phrase across several fields, ranked, with truncation and diacritic folding — is not something a relational query does well or quickly. Zebra is a purpose-built index for exactly that, and it is why Koha can search a million records in the time a LIKE query would take on a hundred thousand.
The cost of any separate index is that it can disagree with the data. Koha keeps them together with a queue: a saved record enqueues an index job, and something has to drain that queue. When the drain stops, the catalogue keeps working perfectly while search quietly goes stale — which is exactly why this failure is so often reported as "Koha lost my records".
It is the same failure shape as the message queue behind notices, and worth recognising as a pattern — see Koha cron jobs.
Troubleshooting
| What you see | What it usually is |
|---|---|
| New records never appear in search | The indexer daemon is stopped, and the cron fallback is commented out. Nothing is draining the queue. |
| Rebuild runs, search is still empty | The Zebra server itself is not running: sudo koha-zebra --start library. |
| Some records index, others do not | Those records fail to export — usually invalid MARC. The record numbers are named in zebra-error.log. |
| Search works, then breaks again in days | Both the daemon and the cron line are active and fighting. Disable one. |
| Rebuild fails part-way with no message | The disk filled during the rebuild. Check df -h and the log. |
| Everything indexes but relevance is wrong | Not an index problem — the record structure or the search field mapping. Reindexing will not change it. |
Would rather not do this yourself? We do it as a service — and if you would rather it were already done, it is on Koha Cloud before you log in.
Related
More on configuration & operations
Answers to the questions that usually arrive with this one.
Koha internal server error: finding the line that caused it
A 500 page is Koha telling you nothing on purpose. The real message is in that instance's error log — here is which file to read, and the two causes that produce most of them.
Backing up Koha with koha-dump — and restoring it
A package install already backs itself up nightly, keeps two days, and writes to a disk that dies with the server. Here is how to check it, and how to restore.
Koha cron jobs: which ones matter, and what breaks silently without each
A package install schedules about fifteen jobs. This is what each one does, when it runs, and the exact symptom a library sees when it stops.
Using a Gmail account as Koha’s SMTP server
Gmail works as Koha’s mail server, but only with an app password and two-step verification on. Here are the exact settings, and the limits worth knowing before you rely on it.

