state.db FTS corruption goes undetected — no integrity check, no repair path
Summary
The messages_fts and messages_fts_trigram FTS5 indexes in state.db can become corrupt ("database disk image is malformed"), silently breaking session_search, /resume, /history, and any feature backed by FTS. There is currently:
- No integrity check on startup —
_init_schema() creates/reconciles tables but never runs PRAGMA integrity_check
- No FTS health validation —
hermes doctor only checks SELECT COUNT(*) FROM sessions; it doesn't validate FTS indexes match the messages table
- No repair command —
hermes sessions has list, prune, stats, rename, export, delete, browse — but no repair
- No auto-recovery — When FTS is corrupt,
_init_schema() catches sqlite3.OperationalError (table missing) but not sqlite3.DatabaseError (table corrupt/malformed)
Root Cause
FTS5 virtual tables and their triggers insert into the FTS index as part of the message INSERT transaction. If that transaction is interrupted mid-commit (force-kill, WAL checkpoint failure, power loss), the FTS and messages tables desync. The _try_wal_checkpoint() runs every 50 writes but is best-effort with bare except Exception: pass — corrupt FTS during checkpoint is silently swallowed.
Reproduction
- Run Hermes with heavy session activity (gateway + CLI + worktree agents sharing state.db)
- Force-kill the process (
taskkill /F /IM hermes.exe on Windows, or SIGKILL on Linux)
- Restart —
session_search returns "database disk image is malformed"
Related Issues
Impact
session_search (the only way for Hermes to recall cross-session context) is completely broken
/resume, /title, /history, /branch all fail
- The only recovery path is manual: stop gateway, export JSON, rebuild from scratch
- Users lose session history if they don't know the manual recovery procedure
state.db FTS corruption goes undetected — no integrity check, no repair path
Summary
The
messages_ftsandmessages_fts_trigramFTS5 indexes instate.dbcan become corrupt ("database disk image is malformed"), silently breakingsession_search,/resume,/history, and any feature backed by FTS. There is currently:_init_schema()creates/reconciles tables but never runsPRAGMA integrity_checkhermes doctoronly checksSELECT COUNT(*) FROM sessions; it doesn't validate FTS indexes match the messages tablehermes sessionshaslist,prune,stats,rename,export,delete,browse— but norepair_init_schema()catchessqlite3.OperationalError(table missing) but notsqlite3.DatabaseError(table corrupt/malformed)Root Cause
FTS5 virtual tables and their triggers insert into the FTS index as part of the message INSERT transaction. If that transaction is interrupted mid-commit (force-kill, WAL checkpoint failure, power loss), the FTS and messages tables desync. The
_try_wal_checkpoint()runs every 50 writes but is best-effort with bareexcept Exception: pass— corrupt FTS during checkpoint is silently swallowed.Reproduction
taskkill /F /IM hermes.exeon Windows, or SIGKILL on Linux)session_searchreturns "database disk image is malformed"Related Issues
Impact
session_search(the only way for Hermes to recall cross-session context) is completely broken/resume,/title,/history,/branchall fail