| name | sqlite-fts5-corruption-rebuild |
| description | Fix SQLite "database disk image is malformed" errors caused by corrupted FTS5 indexes.
Use when: (1) UPDATE/INSERT fails with "stepping, database disk image is malformed" but
PRAGMA integrity_check returns "ok", (2) Only specific records fail to update while others
succeed, (3) Records contain dirty text with tabs, newlines, or unusual characters that
were inserted into FTS5-indexed columns. The misleading error message suggests disk
corruption, but the actual issue is FTS5 index corruption from malformed text content.
|
| author | Claude Code |
| version | 1.0.0 |
| date | "2026-01-23T00:00:00.000Z" |
SQLite FTS5 Index Corruption from Dirty Data
Problem
SQLite returns "database disk image is malformed" (error code 11) when trying to
UPDATE or INSERT records, even though PRAGMA integrity_check reports the database
as "ok". The error only affects specific records, not all writes.
Context / Trigger Conditions
- Error message:
Error: stepping, database disk image is malformed (11)
PRAGMA integrity_check returns ok (misleading!)
- SELECT queries on the same records work fine
- Only certain records fail to update; other records in the same table update successfully
- The affected records contain text with embedded tabs (
\t), newlines (\n), or other
control characters in columns that are indexed by FTS5
- A concurrent process (like a Node.js server) may have the database open
Solution
-
Identify FTS5 tables linked to the affected table:
SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%fts%';
-
Stop any processes holding the database open (the rebuild requires exclusive access):
kill $(lsof -ti :PORT)
-
Rebuild the FTS5 index:
INSERT INTO table_fts(table_fts) VALUES('rebuild');
Replace table_fts with your actual FTS5 table name (e.g., people_fts).
-
Retry the failed operation - it should now succeed.
-
Restart your application server.
Verification
- The previously failing UPDATE/INSERT statement now succeeds
- Full-text search queries still return correct results
- No more "malformed" errors on subsequent writes
Example
sqlite3 data/tracker.db "UPDATE people SET name = 'More' WHERE id = 11;"
sqlite3 data/tracker.db "PRAGMA integrity_check;"
sqlite3 data/tracker.db "SELECT id, name FROM people WHERE id = 11;"
kill $(lsof -ti :3001)
sqlite3 data/tracker.db "INSERT INTO people_fts(people_fts) VALUES('rebuild');"
sqlite3 data/tracker.db "UPDATE people SET name = 'More' WHERE id = 11;"
Prevention
Notes
- The error code 11 (
SQLITE_CORRUPT) is the same as actual disk corruption,
making this hard to diagnose
- The corruption is in the FTS5 shadow tables (
_data, _idx, _docsize),
not the main table, which is why integrity_check passes
- If
rebuild fails with "database is locked", ensure no other process has
the database open (check with lsof or fuser)
- This can also happen when records are deleted or updated externally
(e.g., via sqlite3 CLI) while a WAL-mode connection is active
References