This error occurs when SQLite tries to open a file that does not have a valid SQLite database file format. This typically happens due to database corruption, attempting to open a non-database file, encrypted database without the correct key, or file header corruption. The file lacks the "SQLite format 3" signature at its beginning, which all valid SQLite databases must have.
The SQLITE_NOTADB error (error code 26) indicates that SQLite cannot recognize the file being opened as a valid SQLite database. All valid SQLite database files begin with a 16-byte header signature "SQLite format 3" followed by binary metadata. If this header is missing, corrupted, or the file contains different data entirely, SQLite will refuse to open it and return SQLITE_NOTADB. This error can occur in several scenarios: - The file path points to a non-database file (text file, binary file, etc.) - The database file has become corrupted, particularly the header - An encrypted database is being opened without providing the correct decryption key - Automatic recovery after a crash or power failure failed to restore the database - The file was partially overwritten or truncated by another process
Check the file header using a hex editor or command-line tools to confirm it starts with "SQLite format 3":
# Linux/macOS: Check file signature
hexdump -C your_database.db | head -1
# Should show: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33
# Alternative: Use file command
file your_database.db
# Should output: SQLite 3.x database
# Or check the first bytes with od
od -c your_database.db | head -1
# Should start with: S q l i t e f o r m a t 3If the file does not contain this header, it is either corrupted or not a SQLite database file at all.
Verify the file path is correct and points to an actual database file:
# List the file
ls -lh /path/to/your_database.db
# Check file type
file /path/to/your_database.db
# Verify the path in your application configuration
cat your_app_config.json | grep database
# or
grep DATABASE_PATH .envCommon mistakes:
- Typo in file path
- File extension is wrong
- Path points to a directory instead of a file
- File was renamed or moved to a different location
If using SQLCipher (encrypted SQLite), ensure you provide the correct password before opening:
// Node.js with better-sqlite3 and sql.js (encrypted)
const Database = require('better-sqlite3');
const db = new Database('encrypted.db');
// For encrypted databases, must set key BEFORE any operations
try {
db.pragma('key = "yourpassword"');
db.prepare('SELECT 1').get(); // Test if key works
} catch (err) {
console.error('Wrong password or not an encrypted database:', err.message);
}# Python with sqlcipher
import sqlcipher3 as sqlite3
conn = sqlite3.connect('encrypted.db')
conn.execute('PRAGMA key="yourpassword"')
conn.execute('SELECT 1') # Test if key is correct// C API with SQLCipher
sqlite3 *db;
int rc = sqlite3_open("encrypted.db", &db);
if (rc == SQLITE_OK) {
// Set key BEFORE any other operations
const char *key = "mypassword";
sqlite3_key(db, key, strlen(key));
// Test if key is correct
char *errMsg = NULL;
rc = sqlite3_exec(db, "PRAGMA integrity_check;", NULL, NULL, &errMsg);
if (rc != SQLITE_OK) {
printf("Wrong password: %s\n", errMsg);
}
}If the database is encrypted and you don't know the password, recovery is extremely difficult.
Use the SQLite command-line tool to attempt recovery using the .recover command:
# Try to recover the database
sqlite3 corrupted.db ".recover" > recovered.sql
# If .recover is not available (older SQLite), try .dump
sqlite3 corrupted.db ".dump" > recovered.sql
# Inspect the recovered SQL
head -50 recovered.sql
# Create new database from recovered SQL
sqlite3 recovered.db < recovered.sql
# Verify the new database is valid
sqlite3 recovered.db "PRAGMA integrity_check;"The .recover command is more powerful and can work with partially corrupted files.
If you can partially open the database, run integrity checks:
# Open database and check integrity
sqlite3 your_database.db "PRAGMA integrity_check;"
# More detailed check
sqlite3 your_database.db "PRAGMA integrity_check(10000);"
# Returns list of corruption types found
# Check quick integrity (faster but less thorough)
sqlite3 your_database.db "PRAGMA quick_check;"
# Check specific table
sqlite3 your_database.db "PRAGMA integrity_check(your_table);"Output examples:
- "ok" - Database is valid
- "malformed database" - Header is corrupted
- "parse error" - Table definition error
- Other specific corruption messages
If you have a recent backup, restore it instead of attempting recovery:
# Check if backup exists
ls -la *.db *.bak *.backup
# Restore from backup
cp your_database.db.backup your_database.db
# Verify the restored database
sqlite3 your_database.db "PRAGMA integrity_check;"
# Test database operations
sqlite3 your_database.db "SELECT COUNT(*) FROM main_table;"Backups are the most reliable recovery method. If you have hourly or daily backups, you may only lose a small amount of recent data.
Ensure the file is readable and accessible:
# Check file permissions
ls -l your_database.db
# Ensure current user can read the file
chmod 644 your_database.db # rw- r-- r--
# Check if disk is full (can cause corruption)
df -h /path/to/your_database.db
# Check disk health
# Linux:
smartctl -a /dev/sda # Check SSD/HDD health
dmesg | grep -i error # Check system logs
# macOS:
diskutil info /Volumes/YourDriveDisk full, permission denied, or hardware failures can cause corruption.
If recovery commands fail, try a lower-level approach using hexdump or strings:
# Extract readable data from corrupted file
strings corrupted.db | grep -E "^[A-Z_]+" > extracted_data.txt
# Use specialized SQLite recovery tools
# Online tools like DBRecovery or DataRecovery can sometimes recover data
# Download from: https://www.stellarinfo.com/sqlite-repair.php
# If database was previously exported as SQL, restore from that
sqlite3 new_database.db < exported_backup.sql
# Manually check if there are .wal or .shm files (Write-Ahead Log)
ls -la your_database.db*
# If found: your_database.db-wal or your_database.db-shm
# These might contain recent transactions that can be recoveredWAL files may contain uncommitted transactions that can be recovered.
Understanding SQLite File Format:
A valid SQLite database file has a specific structure:
- Bytes 0-15: Header "SQLite format 3\x00" (in ASCII/hex: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00)
- Bytes 16-19: Page size (default 4096)
- Bytes 20-23: File format write and read versions
- Bytes 24 onwards: Metadata and tables
If any of these are damaged, SQLite cannot read the file.
Write-Ahead Logging (WAL) Recovery:
With WAL mode enabled, SQLite creates additional files:
- database.db: Main database
- database.db-wal: Write-Ahead Log (recent changes)
- database.db-shm: Shared memory file
If the main database is corrupted but WAL files exist, you may recover recent transactions:
# Check if WAL files exist
ls -la your_database.db*
# Try to recover using WAL
sqlite3 your_database.db "PRAGMA journal_mode;" # Check if WAL is enabled
sqlite3 your_database.db "PRAGMA wal_checkpoint(TRUNCATE);" # Flush WALDetecting Corruption Early:
Implement periodic integrity checks in production:
import sqlite3
def check_database_health(db_path):
try:
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
result = cursor.execute("PRAGMA integrity_check;").fetchone()
if result[0] != 'ok':
print(f"Corruption detected: {result[0]}")
return False
return True
except sqlite3.DatabaseError as e:
print(f"Database error: {e}")
return False
# Run health check weekly
check_database_health('app.db')Preventing Corruption:
1. Always close database connections cleanly
2. Use context managers or try/finally blocks
3. Enable WAL mode for safer concurrent access
4. Implement backup strategy (hourly/daily automated backups)
5. Monitor disk space and health
6. Use power backup (UPS) for critical databases
7. Avoid opening database files from multiple processes simultaneously
8. Don't modify database files while they're open in other applications
9. Set proper file permissions (read-only for backups)
10. Regularly test backup restoration to ensure they're valid
Encrypted Database Considerations:
If using SQLCipher for encryption:
- The key must be provided as the first operation after opening
- Key changes require re-encryption of the entire database
- Loss of password = permanent data loss (no recovery possible)
- Encrypted databases have a different header and cannot be opened as regular SQLite files
Recovery Success Rates:
- Backup restoration: 100% (assuming backup is valid)
- .recover command: 70-90% for minor corruption
- Hex editor recovery: 30-50% for severe corruption
- Data loss: Often 5-20% even with successful recovery
SQLITE_CORRUPT_VTAB: Content in virtual table is corrupt
Content in virtual table is corrupt
SQLITE_IOERR_WRITE: Disk I/O error during write
Disk I/O error during write operation
SQLITE_READONLY: Attempt to write a readonly database
How to fix "SQLITE_READONLY: Attempt to write a readonly database" in SQLite
SQLITE_CONSTRAINT_PRIMARYKEY: PRIMARY KEY constraint failed
How to fix "SQLITE_CONSTRAINT_PRIMARYKEY" in SQLite
SQLITE_READONLY_DBMOVED: Database file has been moved since opened
How to fix 'SQLITE_READONLY_DBMOVED: Database file has been moved since opened'