hermes - ✅(Solved) Fix Session store fails to open when SQLite lacks FTS5 module (common on Python 3.11 macOS installs) [1 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Hermes's SQLite session store (hermes_state.py) refuses to open at all when the underlying Python's sqlite3 module wasn't compiled with FTS5 support. This affects common Python installations (e.g. Python 3.11 on macOS built via Homebrew on certain formulae, some pyenv builds). The error message is Error: Could not open session database: no such module: fts5. When this fires, all SQLite-backed features silently break (session history, hermes sessions list, hermes insights, any GUI companion like Scarf that reads state.db) while the user's primary flow still works due to the JSONL fallback.

Error Message

Confirm the Python can't do FTS5

/path/to/hermes/venv/bin/python -c "import sqlite3; sqlite3.connect(':memory:').execute('CREATE VIRTUAL TABLE t USING fts5(x)')"

sqlite3.OperationalError: no such module: fts5

Now run hermes sessions list

hermes sessions list

Error: Could not open session database: no such module: fts5

All .jsonl session files exist on disk in hermes/sessions/,

but state.db's sessions/messages tables stay empty.

Root Cause

hermes_state.py attempts to CREATE VIRTUAL TABLE ... USING fts5(...) unconditionally during DB init. When the sqlite3 compile doesn't include the FTS5 module, this statement raises OperationalError: no such module: fts5, preventing the entire DB from being opened.

Fix Action

Fixed

PR fix notes

PR #13222: fix(hermes_state): gracefully degrade when SQLite build lacks FTS5

Description (problem / solution / changelog)

Problem

Some SQLite builds (Python 3.11 on macOS via certain Homebrew and pyenv formulae) compile `sqlite3` without the FTS5 module. When FTS5 is missing, `CREATE VIRTUAL TABLE ... USING fts5(...)` throws `sqlite3.OperationalError: no such module: fts5`.

Before this patch, that error killed `SessionDB` init completely — every SQLite-backed feature (`hermes sessions list`, `hermes insights`, external tools like Scarf reading `state.db`) failed silently while the JSONL fallback kept the primary WhatsApp/CLI chat flow working. Reported by @chillprakash in #13029 with clear repro on macOS ARM64 + Python 3.11.13.

Fix

Init path (`hermes_state.py:343-378`): catch the `OperationalError` when the message matches `no such module / fts5`, log a one-time warning with a remediation hint (switch to Python 3.12/3.13/3.14 with FTS5 built in, or rebuild SQLite with FTS5 enabled), and set `self._fts5_available = False`. Other `OperationalError`s are still re-raised so legitimate schema bugs aren't swallowed.

Search path (`search_messages`): when `_fts5_available` is `False`, skip the `MATCH` branch entirely and route into the existing LIKE fallback that already handles CJK queries. No new fallback code — just extending the existing condition.

Pre-implement audit

  • A (existing helper): the LIKE fallback for CJK was already there; I reuse it rather than inventing a new one. ✓
  • B (shared callers): `SessionDB` is the single owner; init contract becomes strictly more permissive (never throws FTS5-missing), no downstream contract change. ✓
  • C (broader rival): `gh pr list --search "13029"` returned no rivals. ✓

Testing

  • New `TestFTS5Search::test_search_falls_back_to_like_when_fts5_unavailable` — creates 2 messages, flips `_fts5_available = False`, asserts `search_messages("docker")` returns both messages via LIKE.
  • Full `tests/test_hermes_state.py` suite passes (160/160).

Fixes #13029

Changed files

  • hermes_state.py (modified, +55/-16)
  • tests/test_hermes_state.py (modified, +22/-0)

Code Example

# Confirm the Python can't do FTS5
/path/to/hermes/venv/bin/python -c "import sqlite3; sqlite3.connect(':memory:').execute('CREATE VIRTUAL TABLE t USING fts5(x)')"
# sqlite3.OperationalError: no such module: fts5

# Now run hermes sessions list
hermes sessions list
# Error: Could not open session database: no such module: fts5

# All .jsonl session files exist on disk in hermes/sessions/, 
# but state.db's sessions/messages tables stay empty.

---

def _has_fts5() -> bool:
    try:
        conn = sqlite3.connect(':memory:')
        conn.execute("CREATE VIRTUAL TABLE _t USING fts5(x)")
        conn.close()
        return True
    except sqlite3.OperationalError:
        return False

# In hermes_state.py init:
if _has_fts5():
    # create the fts5 virtual tables for session search
    ...
else:
    # log a warning, skip FTS5 search features, but still init session/messages tables
    log.warning("FTS5 unavailable; session-text search disabled. Session metadata still tracked.")
    ...

---

try:
    import apsw
    # use apsw-backed connection; its SQLite always has FTS5
except ImportError:
    import sqlite3
    # fall through to the Option A graceful-degrade path
RAW_BUFFERClick to expand / collapse

Summary

Hermes's SQLite session store (hermes_state.py) refuses to open at all when the underlying Python's sqlite3 module wasn't compiled with FTS5 support. This affects common Python installations (e.g. Python 3.11 on macOS built via Homebrew on certain formulae, some pyenv builds). The error message is Error: Could not open session database: no such module: fts5. When this fires, all SQLite-backed features silently break (session history, hermes sessions list, hermes insights, any GUI companion like Scarf that reads state.db) while the user's primary flow still works due to the JSONL fallback.

Environment

  • Hermes version: v0.10.0 (2026.4.16)
  • Platform: macOS Darwin 25.2.0, ARM64 (M-series)
  • Python used by venv: 3.11.13 (lacks FTS5)
  • Python alternatives on same machine that DO have FTS5: 3.12.9, 3.13.7, 3.14.3 (all Homebrew)
  • schema_version in state.db: 6

Reproduction

# Confirm the Python can't do FTS5
/path/to/hermes/venv/bin/python -c "import sqlite3; sqlite3.connect(':memory:').execute('CREATE VIRTUAL TABLE t USING fts5(x)')"
# sqlite3.OperationalError: no such module: fts5

# Now run hermes sessions list
hermes sessions list
# Error: Could not open session database: no such module: fts5

# All .jsonl session files exist on disk in hermes/sessions/, 
# but state.db's sessions/messages tables stay empty.

Impact

  1. hermes sessions list returns error — user can't see session history.
  2. hermes insights is non-functional (depends on state.db).
  3. External tools that read state.db (e.g. Scarf macOS GUI companion) show empty views — hard to diagnose for users because Hermes's own core flow (WhatsApp/CLI chat) keeps working via JSONL fallback, so users think Hermes is working fine.
  4. Warning in gateway.log: SQLite session store unavailable, falling back to JSONL: no such module: fts5 — correctly logged but easy to miss among other startup messages.

Root cause

hermes_state.py attempts to CREATE VIRTUAL TABLE ... USING fts5(...) unconditionally during DB init. When the sqlite3 compile doesn't include the FTS5 module, this statement raises OperationalError: no such module: fts5, preventing the entire DB from being opened.

Suggested fix — three reasonable approaches

Option A (preferred): Detect FTS5 at startup, degrade gracefully

def _has_fts5() -> bool:
    try:
        conn = sqlite3.connect(':memory:')
        conn.execute("CREATE VIRTUAL TABLE _t USING fts5(x)")
        conn.close()
        return True
    except sqlite3.OperationalError:
        return False

# In hermes_state.py init:
if _has_fts5():
    # create the fts5 virtual tables for session search
    ...
else:
    # log a warning, skip FTS5 search features, but still init session/messages tables
    log.warning("FTS5 unavailable; session-text search disabled. Session metadata still tracked.")
    ...

This keeps session/messages tables functional (so Scarf and hermes sessions list work), just without FTS5-backed search. Users upgrade their Python when convenient.

Option B: Prefer apsw when available (ships with FTS5-enabled SQLite)

try:
    import apsw
    # use apsw-backed connection; its SQLite always has FTS5
except ImportError:
    import sqlite3
    # fall through to the Option A graceful-degrade path

Option C: Document the dependency clearly Add a preflight check in hermes doctor that confirms FTS5 availability and surfaces a remediation hint ("Rebuild venv with Python 3.12+ or install apsw").

Happy to PR

I can submit a PR implementing Option A if that's the preferred direction. It preserves backward compatibility, fixes the silent-break behavior, and doesn't add runtime dependencies.

Related

Similar graceful-degrade pattern already exists in the gateway logs output: the JSONL fallback IS engaged when state.db fails. The fix here just extends the same pattern to keep the DB opened for the non-FTS5 tables rather than refusing entirely.

extent analysis

TL;DR

The most likely fix is to detect FTS5 support at startup and degrade gracefully if it's not available, allowing the session database to open without FTS5-backed search features.

Guidance

  • Check if the Python installation has FTS5 support by attempting to create a virtual table using FTS5, as shown in the _has_fts5 function in the suggested fix.
  • If FTS5 is not available, log a warning and skip creating FTS5 virtual tables, but still initialize the session and messages tables.
  • Consider using the apsw library as a fallback, which ships with FTS5-enabled SQLite.
  • Add a preflight check in hermes doctor to confirm FTS5 availability and provide a remediation hint if it's not available.

Example

def _has_fts5() -> bool:
    try:
        conn = sqlite3.connect(':memory:')
        conn.execute("CREATE VIRTUAL TABLE _t USING fts5(x)")
        conn.close()
        return True
    except sqlite3.OperationalError:
        return False

Notes

The suggested fix prioritizes backward compatibility and doesn't add runtime dependencies. However, it's essential to test the implementation thoroughly to ensure it works as expected in different environments.

Recommendation

Apply the workaround by detecting FTS5 support at startup and degrading gracefully if it's not available, as described in Option A. This approach allows the session database to open without FTS5-backed search features, providing a functional workaround for users with Python installations lacking FTS5 support.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING