SQLite "file is not a database" — Corrupt or Wrong File
Fix "file is not a database" by checking the SQLite magic header, ruling out an HTML error page or wrong path, and restoring from backup.
Symptoms
- SQLite error: "file is not a database" when opening a path
- The file was recently downloaded or restored
- The app creates a zero-byte file then fails to read it
Possible causes
- The file is not SQLite at all (an HTML error page saved as .db, or a different format)
- The path is wrong and points at an unrelated existing file
- The database header is corrupt from an interrupted write or disk issue
Diagnosis steps
Inspect the file header
head -c 16 app.db | xxdInterpretation
A valid SQLite file begins with the magic string "SQLite format 3\0"; anything else is not SQLite.
Check size and path
ls -l app.db && file app.dbInterpretation
A zero-byte or HTML file reveals a wrong path or a failed download.
Root cause
SQLite identifies a database by the 16-byte magic header. If that header is absent—because the file is HTML, a different format, empty, or corrupted—opening it as a database fails with "file is not a database".
Fix
Point at the correct path, ensure the file is a real SQLite database, validate the header before use, and if corruption is confirmed restore from backup and check the filesystem.
Risk note
Attempting to recover a corrupt database by deleting and recreating it loses data; back up the damaged file first.
Verify the fix
Open the correct file and confirm PRAGMA integrity_check returns ok; assert the header matches the magic string.
Symptoms
When you hit “SQLite “file is not a database” — Corrupt or Wrong File”, guessing wastes time. The guide below follows evidence: reproduce the symptom, run targeted diagnostics, identify the root cause, apply the fix, and verify it with concrete checks.
Observed symptoms include:
- SQLite error: “file is not a database” when opening a path
- The file was recently downloaded or restored
- The app creates a zero-byte file then fails to read it
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Inspect the file header
head -c 16 app.db | xxd
A valid SQLite file begins with the magic string “SQLite format 3\0”; anything else is not SQLite.
Step 2: Check size and path
ls -l app.db && file app.db
A zero-byte or HTML file reveals a wrong path or a failed download.
Likely contributors, in order of frequency:
- The file is not SQLite at all (an HTML error page saved as .db, or a different format)
- The path is wrong and points at an unrelated existing file
- The database header is corrupt from an interrupted write or disk issue
Root Cause
SQLite identifies a database by the 16-byte magic header. If that header is absent—because the file is HTML, a different format, empty, or corrupted—opening it as a database fails with “file is not a database”.
The Fix
Point at the correct path, ensure the file is a real SQLite database, validate the header before use, and if corruption is confirmed restore from backup and check the filesystem.
Watch out: Attempting to recover a corrupt database by deleting and recreating it loses data; back up the damaged file first.
# verify the magic header before opening
head -c 16 app.db | xxd
# expected: 5351 4c69 7465 2066 6f72 6d61 7420 3300 (
# integrity check after opening
sqlite3 app.db 'PRAGMA integrity_check;'
# recover from a good backup rather than recreating
cp app.db.bak app.db
Verify and Prevent
Open the correct file and confirm PRAGMA integrity_check returns ok; assert the header matches the magic string.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.