The SQLITE_IOERR error indicates the operating system encountered an I/O error while reading or writing database files. This typically stems from file permissions, filesystem issues, or hardware problems rather than insufficient disk space.
The SQLITE_IOERR error (error code 10) occurs when SQLite cannot complete an operation because the operating system reported an I/O error. This is a generic error code that covers various disk-related failures detected at the OS level. Unlike SQLITE_FULL which specifically indicates a full disk, SQLITE_IOERR suggests problems with the underlying filesystem, file permissions, or hardware. The error often occurs during read, write, or fsync operations on the database file or its associated journal/WAL files. SQLite provides extended error codes (like SQLITE_IOERR_READ, SQLITE_IOERR_WRITE, SQLITE_IOERR_FSYNC) that identify the specific I/O operation that failed, helping narrow down the root cause.
Verify that your application has read and write access to the database file, its directory, and any journal/WAL files:
# Check permissions on database file
ls -l /path/to/database.db
# Check directory permissions
ls -ld /path/to/
# Ensure write access to directory (needed for journal files)
chmod 755 /path/to/
chmod 644 /path/to/database.db
# If using WAL mode, check for -wal and -shm files
ls -l /path/to/database.db-wal
ls -l /path/to/database.db-shmThe database directory must be writable because SQLite creates temporary journal and lock files during transactions.
Get more specific error information by enabling SQLite extended result codes:
// C API
sqlite3_extended_result_codes(db, 1);
int extended_code = sqlite3_extended_errcode(db);# Python sqlite3
import sqlite3
conn = sqlite3.connect('database.db')
# Extended codes are enabled by default in Python
try:
conn.execute("...")
except sqlite3.OperationalError as e:
print(f"Error: {e}")// Node.js better-sqlite3
const Database = require('better-sqlite3');
const db = new Database('database.db');
// Check error.code property for extended codesExtended codes like SQLITE_IOERR_READ (266), SQLITE_IOERR_WRITE (778), or SQLITE_IOERR_FSYNC (1034) help identify which operation failed.
Check for filesystem corruption that might affect the database:
# Linux: Check filesystem (unmount first if possible)
sudo fsck /dev/sdX1
# Check disk health with SMART
sudo smartctl -a /dev/sdX
# For mounted filesystems, check dmesg for I/O errors
dmesg | grep -i "i/o error"
dmesg | grep -i "sector"
# Check database file integrity
sqlite3 database.db "PRAGMA integrity_check;"If integrity_check reports corruption, you may need to recover from a backup or use the .recover command.
Some network filesystems and exotic filesystem types can cause issues:
# Check filesystem type
df -T /path/to/database.db
# Avoid SQLite on network filesystems when possible
# NFS/CIFS have locking and caching issuesNetwork filesystem workarounds:
1. Copy database to local filesystem before accessing
2. Use SQLite's shared memory and WAL mode carefully
3. Consider using a database server (PostgreSQL/MySQL) instead
For F2FS filesystems, ensure you're using a recent kernel version as older versions had compatibility issues.
Ensure no other process has an exclusive lock on the database:
# Linux: Find processes with file open
lsof /path/to/database.db
# Check for stuck lock files
ls -la /path/to/database.db-journal
rm /path/to/database.db-journal # Only if no other process is using it
# For WAL mode
ls -la /path/to/database.db-wal
ls -la /path/to/database.db-shmIf lock files exist when no process is using the database, they may be stale and can be removed.
Antivirus, EDR, or security software may interfere with database file access:
# Temporarily disable antivirus to test (Linux with ClamAV)
sudo systemctl stop clamav-daemon
# Check SELinux denials
sudo ausearch -m avc -ts recent
# Check AppArmor denials
sudo journalctl | grep DENIEDIf security software is the cause, add exceptions for your database directory or SQLite process.
For Deep Security or similar EDR tools, check vendor documentation for SQLite-specific exclusions.
Create a test database to isolate the issue:
# Create test database in /tmp
sqlite3 /tmp/test.db "CREATE TABLE test(id INTEGER PRIMARY KEY, data TEXT);"
sqlite3 /tmp/test.db "INSERT INTO test(data) VALUES('test');"
sqlite3 /tmp/test.db "SELECT * FROM test;"If the test succeeds:
- The issue is specific to your database file or location
- Try moving the original database to a different location
- Check if the original database file is corrupted
If the test fails:
- The issue is systemic (permissions, filesystem, hardware)
- Check system logs and disk health
Extended Error Code Reference:
SQLite provides over 20 extended IOERR codes. Key ones include:
- SQLITE_IOERR_READ (266): Read operation failed
- SQLITE_IOERR_WRITE (778): Write operation failed
- SQLITE_IOERR_FSYNC (1034): Flush/sync operation failed
- SQLITE_IOERR_ACCESS (3338): File access permissions issue
- SQLITE_IOERR_LOCK (3850): File locking operation failed
- SQLITE_IOERR_CORRUPTFS (8458): Filesystem corruption detected
Network Filesystem Considerations:
SQLite's official documentation warns against using network filesystems due to locking inconsistencies and caching issues. NFS and CIFS can cause false "disk I/O error" reports when file locking protocols fail. If you must use network storage, consider:
- Mounting with nolock option (disables locking - use with caution)
- Using SQLite in WAL mode with PRAGMA locking_mode=EXCLUSIVE
- Implementing application-level locking instead of relying on filesystem locks
- Using a proper client-server database instead
Journal Mode Impact:
Different journal modes have different I/O patterns:
- DELETE mode (default): Creates and deletes journal files frequently
- WAL mode: Maintains persistent -wal and -shm files
- MEMORY mode: Reduces disk I/O but loses crash recovery
If you encounter I/O errors with WAL mode, switching to DELETE mode may help diagnose whether the issue is with the main database file or auxiliary files.
Recovery from Corruption:
If integrity_check reveals corruption, recovery options include:
# Dump recoverable data
sqlite3 corrupted.db ".recover" | sqlite3 recovered.db
# Or use .dump for schema and data
sqlite3 corrupted.db ".dump" | sqlite3 new.dbThe .recover command (SQLite 3.32+) is more robust than .dump for corrupted databases.
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'