How to fix SQLITE_CORRUPT_VTAB: Content in virtual table is corrupt in SQLite
This error occurs when SQLite detects corruption in a virtual table, most commonly in FTS (Full Text Search) tables. It indicates that the virtual table's internal data structures have been damaged or contain invalid data.
Quick fix
Fixes SQLITE_CORRUPT_VTAB
SELECT name, sql FROM sqlite_master
WHERE type = 'table' AND sql LIKE '%VIRTUAL%';- Check which virtual table is affected
- Attempt to rebuild the virtual table index
- Run integrity check on the virtual table
- Back up your data and recreate the virtual table
SELECT name, sql FROM sqlite_masterWHERE type = 'table' AND sql LIKE '%VIRTUAL%';SQLITE_CORRUPT_VTAB: Content in virtual table is corrupt
What this error means
The SQLITE_CORRUPT_VTAB error is an extended error code for SQLITE_CORRUPT that is specifically used by virtual tables. Virtual tables in SQLite are interfaces to external data sources or special-purpose tables like FTS3, FTS4, and FTS5 (Full Text Search) tables. When you see this error, it means the virtual table implementation has detected that its internal content is corrupt or malformed. Virtual tables maintain their data in "shadow tables" - hidden tables that store the actual data and indexes. When these shadow tables become corrupted, inconsistent, or contain data that violates the virtual table's invariants, the virtual table module returns SQLITE_CORRUPT_VTAB to indicate the problem. This error is different from general database corruption because it's specific to the virtual table mechanism and its implementation. The main database file might be fine, but the specific virtual table's internal structures are damaged.
Typical symptoms
- Queries on FTS tables fail with "database disk image is malformed"
- Virtual table operations that previously worked now throw SQLITE_CORRUPT_VTAB
- Integrity checks pass for the main database but virtual table queries fail
- Error occurs after an interrupted transaction involving a virtual table
- FTS searches return corruption errors even though the base tables are intact
Common causes
- Improper transaction handling when updating FTS tables, such as triggering updates without proper parent table values
- Updating an FTS5 table when it doesn't yet contain any data during an upsert operation
- Shadow tables used by FTS virtual tables becoming corrupted or missing records
- Failed transactions that partially modified virtual table structures without being rolled back
- Application crashes or unexpected shutdowns during virtual table write operations
- Concurrent access violations when multiple processes modify the same virtual table
- Bugs in custom virtual table implementations that write invalid data
How to fix "SQLITE_CORRUPT_VTAB: Content in virtual table is corrupt"
First, identify the specific virtual table causing the error by examining your query and error stack trace.
List all virtual tables in your database:
SELECT name, sql FROM sqlite_master
WHERE type = 'table' AND sql LIKE '%VIRTUAL%';If you're using FTS tables, they'll show up with CREATE VIRTUAL TABLE statements. Note the table name for the next steps.
For FTS tables (FTS3, FTS4, FTS5), try rebuilding the index which can often fix corruption:
For FTS3/FTS4:
INSERT INTO your_fts_table(your_fts_table) VALUES('rebuild');For FTS5:
INSERT INTO your_fts_table(your_fts_table, rank) VALUES('rebuild', 0);Replace your_fts_table with your actual table name. This forces the virtual table to rebuild its internal structures from the source data.
Check the integrity of the virtual table specifically:
For FTS tables:
INSERT INTO your_fts_table(your_fts_table) VALUES('integrity-check');This will report any issues found in the virtual table's internal structures. If it reports errors, the corruption is confirmed and you may need to recreate the table.
If rebuilding doesn't work, you'll need to recreate the virtual table:
1. First, back up the source data (the actual table that the FTS indexes):
CREATE TABLE your_table_backup AS SELECT * FROM your_table;2. Drop the corrupted virtual table:
DROP TABLE your_fts_table;3. Recreate the virtual table with the same schema:
CREATE VIRTUAL TABLE your_fts_table USING fts5(column1, column2);4. Repopulate it from the source table:
INSERT INTO your_fts_table SELECT column1, column2 FROM your_table;Review your code for improper transaction handling around virtual tables:
Bad pattern (can cause corruption):
// Triggering FTS update without proper parent table data
db.run("BEGIN TRANSACTION");
db.run("UPDATE fts_table SET content = ?", [newContent]); // FTS not ready
db.run("COMMIT");Good pattern:
db.run("BEGIN TRANSACTION");
try {
// Insert/update parent table first
db.run("INSERT INTO documents (id, text) VALUES (?, ?)", [id, text]);
// FTS table updates automatically via trigger or explicit insert
db.run("COMMIT");
} catch (error) {
db.run("ROLLBACK");
throw error;
}Ensure that if an INSERT or UPDATE that would trigger a virtual table update fails, the entire transaction is rolled back.
Advanced notes
FTS3 vs FTS4 vs FTS5: If you're still using FTS3 or FTS4, consider migrating to FTS5. FTS5 has better error handling, improved performance, and is more resistant to corruption. It's also the actively maintained version.
Custom Virtual Tables: If you've implemented a custom virtual table module, ensure that your xUpdate, xBegin, and xCommit methods properly validate data before writing and correctly handle rollback scenarios. Virtual table implementations must maintain consistency of their shadow tables even when transactions are aborted.
WAL Mode Considerations: If your database is in WAL (Write-Ahead Logging) mode, ensure that checkpoint operations complete successfully. Incomplete checkpoints can leave virtual tables in an inconsistent state. You can manually checkpoint with PRAGMA wal_checkpoint(FULL);
Preventing Future Corruption:
- Always use transactions when modifying tables that have FTS virtual tables associated with them
- Ensure proper error handling in triggers that update virtual tables
- Don't manually modify the shadow tables (tables with names like your_fts_table_content, your_fts_table_segdir, etc.)
- Use PRAGMA integrity_check regularly to detect corruption early
Recovery Tools: For severe corruption where rebuilding doesn't work, SQLite provides a recovery API (available in SQLite 3.37.0+) that can extract data from corrupted databases. The .recover command in the sqlite3 shell can help salvage data from damaged virtual tables.
Frequently asked questions
- What does "SQLITE_CORRUPT_VTAB" mean?
- The SQLITE_CORRUPT_VTAB error is an extended error code for SQLITE_CORRUPT that is specifically used by virtual tables. Virtual tables in SQLite are interfaces to external data sources or special-purpose tables like FTS3, FTS4, and FTS5 (Full Text Search) tables. When you see this error, it means the virtual table implementation has detected that its internal content is corrupt or malformed.
- How do I fix "SQLITE_CORRUPT_VTAB"?
- This error occurs when SQLite detects corruption in a virtual table, most commonly in FTS (Full Text Search) tables. It indicates that the virtual table's internal data structures have been damaged or contain invalid data.
- What causes "SQLITE_CORRUPT_VTAB"?
- Improper transaction handling when updating FTS tables, such as triggering updates without proper parent table values Updating an FTS5 table when it doesn't yet contain any data during an upsert operation Shadow tables used by FTS virtual tables becoming corrupted or missing records
- Is the "SQLITE_CORRUPT_VTAB" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.