fix(session): survive, prevent, and explain missing SQLite FTS5#35103
Conversation
The salvaged contributor commit guarded only messages_fts. Current main also creates a second virtual table, messages_fts_trigram (CJK substring search), whose CREATE VIRTUAL TABLE ... USING fts5 still raised "no such module: fts5" on builds without FTS5 — re-crashing SessionDB init. Wrap the trigram setup with the same guard, and broaden the test's no-fts5 mock to fail BOTH tables so the regression test actually exercises a faithful no-FTS5 build.
uv's python-build-standalone distributions only gained FTS5 in mid-2025 (#694). A stale interpreter already in uv's store — which `uv python find` reuses without checking — can lack it, leaving the supported install with a SQLite that can't create the FTS5 virtual tables hermes_state.py needs for full-text session search ("no such module: fts5"). check_python now probes the resolved interpreter for FTS5 and, if missing, reinstalls the latest patch for $PYTHON_VERSION (which has FTS5) and re-resolves. If an FTS5-capable Python still can't be obtained (offline, pinned env), it warns and continues — Hermes degrades gracefully and only disables session search. No bundled second SQLite, no user action.
When FTS5 is missing the warning now explains the likely cause (an unsupported / pip-managed Python whose bundled SQLite lacks FTS5) and links the supported install at hermes-agent.nousresearch.com, instead of just logging the raw error.
🔎 Lint report:
|
|
I tried testing this and it seems to not work as intended. Workaround (posted on discord) works: Removing my workaround by deleting the working system python: I manually checked ~/.hermes/hermes-agent/install.sh and it does have the fix in this PR. I can get my system working again, so I am providing this just to help others. |
|
Took a stab at the "survive" part of this PR and simplified it a bit so its actually working, let me know if I should open a PR: main...obtitus:hermes-agent:fix/survive-missing-fts5 Note: This does not fix the missing fts5 when using uv installed python, but ensure you can still use e.g. |
Summary
Hermes no longer dies with
Could not open session database: no such module: fts5on installs whose bundled SQLite lacks FTS5, and the supported installer now guarantees an FTS5-capable Python so it doesn't happen in the first place.Three layers:
SessionDBopens without FTS5, keeping session/message persistence and disabling only full-text search.install.shprobes the resolved uv-managed Python for FTS5 and reinstalls a current build if a stale one lacks it.Supersedes #10972 — includes @LeonSGP43's graceful-degradation commit (authorship preserved) plus follow-ups. Fixes #10897.
Root cause
SessionDB.__init__unconditionally runsCREATE VIRTUAL TABLE ... USING fts5(...). SQLite builds compiled without the FTS5 module raiseOperationalError: no such module: fts5, which propagated out of__init__and took down the entire session store. uv's python-build-standalone distributions only gained FTS5 in mid-2025 (astral-sh/python-build-standalone#694), so a stale interpreter already in uv's store — whichuv python findreuses without checking — can ship a SQLite 3.49.x without FTS5.Changes
hermes_state.py:_fts_enabledflag; guard bothmessages_ftsand themessages_fts_trigramCJK index so an FTS5-unavailable error degrades (one warning) instead of raising.search_messages()early-returns[]when disabled. Warning now points at the supported install.scripts/install.sh:_python_has_fts5()probe +ensure_fts5()— aftercheck_pythonresolves an interpreter, verify FTS5; if missing,uv python install <ver> --reinstalland re-resolve. Warns and continues if an FTS5 build still can't be obtained (offline / pinned env).tests/test_hermes_state.py: regression test simulating a no-FTS5 SQLite runtime; mock fails both virtual tables so the test exercises a faithful no-FTS5 build.Validation
OperationalError(DB unusable)_fts_enabled=False, one actionable warningsearch_messages()(no FTS5)[]optimize_fts()(no FTS5)_fts_enabled=True, search hits)Installer probe verified both ways against real interpreters (true-positive on FTS5 python, true-negative on a simulated no-FTS5 one); runtime path E2E-verified with real imports; targeted tests 4/4.
Closes #10897. Supersedes #10972.
Infographic