state.db are, why
maintenance commands refuse while a writer is live) see
Session storage recovery.
state.db stores two different data classes:
sessionsandmessagesare the canonical transcript.messages_fts*tables and their sync triggers are derived search indexes.
Live behavior when FTS is corrupt
If an FTS write or search reports the corruption error class,SessionDB:
- records the durable
fts_stalemarker; - removes the FTS sync triggers in the same transaction;
- retries canonical writes without the derived-index sinks; and
- serves searches from canonical rows through the
LIKEfallback.
FTS5('rebuild'). Existing recovery
ownership remains unchanged: a later SessionDB open may rebuild under the
cross-process admission lock and foreign-holder guard. If that guarded rebuild
cannot run, FTS remains detached, canonical writes stay available, and
mibyan doctor reports the explicit repair command.
Live behavior when the file itself is corrupt
If a live write reports bareSQLITE_CORRUPT / SQLITE_NOTADB (database disk image is malformed, file is not a database) with no FTS provenance,
the damage is in a canonical B-tree, the schema, or the freelist. SessionDB
then quarantines that handle (StateDbCorruptError):
- the failing write propagates the typed error and nothing is retried;
- later writes on the handle fail immediately without touching the file;
- the handle never reopens its connection after
close(); and close()skips its explicit WAL checkpoint.
messages_fts_trigram_data leaf) and turned a damaged-but-readable file into
one that no longer opened at all. Skipping the explicit checkpoint is the
second line of defence; on Python 3.12+ the quarantine also disables
SQLite’s own last-connection checkpoint (SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE),
so the -wal sidecar survives close() for forensics. On Python 3.11 that
switch is unavailable and SQLite may still checkpoint once on close, so copy
state.db, state.db-wal and state.db-shm together before restarting
anything.
The gateway and the agent flush path treat the quarantine like a replaced
file: pending transcripts go to sessions/<id>.jsonl and the gateway
pending_messages/ spool instead of the retry queue, and the FTS one-shot
rebuild never runs on the damaged file. The quarantine is per process — the
shared handle stays poisoned for every holder until the process restarts on a
repaired or restored file. Do not run mibyan doctor --fix while the gateway
is still up. Next steps:
state-snapshots/.
Explicit repair
Stop every process that can open the profile database before repairing it. Keep them stopped for the complete repair and verification window.sessions repair creates a SQLite backup by default and performs structural
work through the repository’s guarded snapshot-and-promotion path. Do not copy
state.db, state.db-wal, and state.db-shm independently with cp; those
files are one live SQLite image.
After repair, verify the health probe, stale marker, trigger set, and canonical
row counts before restarting the gateway:

