← Debugging Guides

阅读中文版本

SQLite — database disk image is malformed

Diagnose SQLite corruption with integrity checks, preserve the file, recover data with .recover or a dump, and fix disk or lifecycle causes.

advanceddebuggingsqlitedatabase

Symptoms

  • DatabaseError: database disk image is malformed
  • Queries fail on specific tables while other tables still work
  • The error appears after a power loss, disk full, or abrupt process kill
  • PRAGMA integrity_check reports errors

Possible causes

  • The process or machine crashed during a write
  • The disk filled while SQLite was writing
  • The database file was copied while a write or WAL checkpoint was in progress
  • The database is on a network filesystem with unreliable locking
  • Hardware or filesystem corruption affected the file

Diagnosis steps

Stop writes and preserve the original file

cp app.db app.db.corrupt-$(date +%s) && sqlite3 app.db 'PRAGMA integrity_check;'

Interpretation

Copy the file before any repair attempt. integrity_check reports ok or lists the damaged pages and indexes.

Isolate the damaged parts

sqlite3 app.db 'PRAGMA quick_check; SELECT name FROM sqlite_master WHERE type="table";'

Interpretation

Determine whether the whole file or one table/index is affected, and whether the schema is readable.

Check the environment

df -h . && dmesg | tail -20

Interpretation

A full disk, I/O errors, or an unclean shutdown explains how the damage occurred and whether it will recur.

Root cause

SQLite detected a structurally invalid database file. The corruption is usually caused by an interrupted write, disk exhaustion, an unsafe copy, or a filesystem that does not provide reliable locking.

Fix

Restore from a verified backup if available. Otherwise recover into a new database with sqlite3 .recover or a dump, verify the recovered data, and switch the application. Fix the disk, copy, and shutdown practices that caused the damage.

Risk note

Running VACUUM or writes on a corrupt database can make recovery harder. Do not overwrite the original file before copying it.

Verify the fix

Run PRAGMA integrity_check on the recovered database, compare row counts and key tables with the last known good backup, and run application read/write tests. Enable WAL, busy_timeout, and safe backup procedures to prevent recurrence.

Preserve before repair

Corruption investigations often destroy evidence. Copy the database file, including any WAL or shared-memory files, before running repair commands. Then run PRAGMA integrity_check on the copy and record the output. If the database is still open by the application, stop writes first.

cp app.db app.db.corrupt
sqlite3 app.db 'PRAGMA integrity_check;'

Recover into a new file

If a verified backup exists, restore it and replay what is missing. Otherwise use sqlite3 app.db ".recover" | sqlite3 recovered.db to salvage readable rows into a fresh database. Compare counts and key records; recovered data may omit damaged pages. Never point the application at the corrupted file while repairing it.

Fix the cause

Corruption is a symptom of an unsafe write lifecycle. Check disk space, power stability, and whether the database lives on NFS or SMB. Copying a live database without the backup API can produce an inconsistent file. Use SQLite’s backup API or a stopped process. A recovered database on the same broken filesystem will corrupt again.

Verify and prevent

Run integrity checks on the recovered file, test application reads and writes, and keep the corrupted copy until the incident is closed. Enable WAL and a busy timeout, monitor disk space, and schedule integrity checks for critical databases. Test the restore procedure, not only the backup.