# Known Hermes DB Corruption Signatures

## TLS-overwritten kanban.db

**Detection:** `file ~/.hermes/kanban.db` returns "data" (not "SQLite 3.x database").
Hex header shows `17 03 03` at byte offset 5 (TLS 1.3 record header).

**Cause:** An HTTPS response body was written into the file path instead of SQLite data.
This can happen when a download/wget/curl command targets the wrong output path,
or when a process writes TLS-encrypted data to a file that should be a database.

**Fix:**
```bash
mv ~/.hermes/kanban.db ~/.hermes/kanban.db.corrupted
hermes kanban init
```

**Observed:** Jun 4 2026 — 100KB file, corrupted at least since May 28 (file mtime).
Kanban dispatcher flooded error log with 726 repeated errors over 1h+ before gateway crashed.
The corrupted file survived 3+ gateway restarts until manually deleted.

## Zero-byte sessions/state.db

**Detection:** `ls -la ~/.hermes/sessions/state.db` shows 0 bytes.
`file` returns "empty".

**Cause:** The FTS5 session search database was created but never populated, or
was truncated on gateway restart. This file is a separate FTS5 index for the
`session_search` tool, not the main project state DB.

**Fix:**
```bash
rm ~/.hermes/sessions/state.db
# Hermes recreates it on the next session write
```

**Note:** Does NOT affect conversation context — only affects `session_search`
tool across sessions.

## FTS5 "invalid file format" errors

**Detection:** Error log shows `invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'`

**Cause:** FTS5 index in state.db desynchronized from the underlying messages table.
Often triggered by unclean shutdowns or gateway crashes mid-write.

**Fix:**
```python
import sqlite3
conn = sqlite3.connect('/home/rurouni/.hermes/state.db')
c = conn.cursor()
c.execute('INSERT INTO messages_fts(messages_fts) VALUES("rebuild")')
c.execute('INSERT INTO messages_fts_trigram(messages_fts_trigram) VALUES("rebuild")')
conn.commit()
```

**Verify:**
```python
c.execute('SELECT count(*) FROM messages')
c.execute('SELECT count(*) FROM messages_fts')
# Both counts should match
```

## Gateway TEMPFAIL (exit code 75) Cascade Pattern

The cascade proceeds in a predictable order:
1. Primary provider rate-limited (HTTP 429) → fallback triggers
2. Fallback provider credit-exhausted (HTTP 402) → no working providers
3. Agent hits max_turns/iterations budget, context gets compacted repeatedly
4. Gateway exits with SystemExit(75) after all non-retryable failures
5. systemd auto-restarts → fresh session, zero history

**Pattern from Jun 4 2026 crash:**
```
deepseek-v4-flash (opencode-go) → HTTP 429 (monthly limit)
  → qwen/q3-coder (openrouter) → HTTP 402 (no credits)
    → TEMPFAIL exit → session wiped
```

**Prevention:** Keep at least **two independent working providers**. When one is
a free tier with monthly caps, the fallback MUST have credits.
