pgref.dev/sqlite/errors/SQLITE_IOERR
SQLITE_IOERRERRORTier 3 — Handle with care✅ HIGH confidence

disk I/O error

Category: I/O ErrorVersions: All SQLite versions

🔴 Production Risk Error

SQLITE_IOERR in production almost always means the database file is in an unknown state. Immediately stop writes, take a file-system backup of the .db and .db-wal files, run PRAGMA integrity_check, and restore from a verified backup if corruption is found.

What this means

SQLITE_IOERR (result code 10) is returned when the SQLite VFS layer encounters an unexpected error from the operating system during a read or write to the database file, WAL file, or journal file. It almost always indicates a hardware or OS-level problem — full disk, failing drive, NFS timeout, or a permissions error on a file that was already open.

Why it happens

  1. 1The filesystem has run out of disk space mid-write
  2. 2A network filesystem (NFS, CIFS) disconnected during a transaction
  3. 3The storage device is reporting I/O errors (failing SSD or HDD)
  4. 4The application process lost write permission on the database file after the connection was opened
  5. 5Antivirus or security software intercepting and blocking file writes

How to reproduce

The disk fills up completely during a large INSERT, preventing the journal from being written.

trigger — this will ERROR
# This cannot be easily demonstrated in :memory: mode.
# In a real environment, fill the disk and then attempt a write:
import sqlite3
conn = sqlite3.connect('/mnt/nearly-full/demo.db')
# When disk fills during commit:
# sqlite3.OperationalError: disk I/O error
sqlite3.OperationalError: disk I/O error

Fix 1: Free disk space and retry

When a full filesystem is the root cause.

fix
import shutil
total, used, free = shutil.disk_usage('/')
print(f"Free: {free // (1024**3)} GB")
# Free space by deleting temp files, then reconnect and retry.

Why this works

SQLITE_IOERR is a hard error that cannot be resolved at the SQL level — it requires fixing the underlying OS or hardware condition. After recovery, the database may need integrity checking.

Fix 2: Run integrity check after recovery

After resolving the underlying I/O error, verify the database is not corrupted.

fix
import sqlite3
conn = sqlite3.connect('mydb.db')
result = conn.execute('PRAGMA integrity_check').fetchall()
print(result)  # [('ok',)] if healthy

Why this works

integrity_check traverses all pages of the database B-tree and verifies structural consistency. If the I/O error interrupted a write mid-page, this will reveal corruption that requires restore from backup.

What not to do

Continue using the database after SQLITE_IOERR without an integrity check

Why it's wrong: An interrupted write may have left a page partially written, silently corrupting data that will only surface as incorrect query results later.

Version notes

SQLite 3.7.17+SQLITE_IOERR has over 20 extended codes (e.g. SQLITE_IOERR_READ=266, SQLITE_IOERR_WRITE=778) that identify which VFS operation failed.

Dangerous variant

⚠️ Warning

SQLITE_IOERR_WRITE (778) — the specific error for a failed write() syscall. If this occurs during a journal sync the original pages may not be backed up, making rollback impossible and leaving the database in an inconsistent state.

Sources

📚 Official docs: https://www.sqlite.org/rescode.html#ioerr

🔧 Source ref: sqlite3.h — SQLITE_IOERR = 10

📖 Further reading: SQLite VFS documentation

📖 Further reading: SQLite atomic commit

Confidence assessment

✅ HIGH confidence

The base code is stable. Extended IOERR codes are well documented in sqlite3.h. The remediation advice (stop writes, check integrity, restore from backup) reflects SQLite project guidance.

See also

⚙️ This error reference was generated with AI assistance and reviewed for accuracy. Examples are provided to illustrate common scenarios and may not cover every case. Always test fixes in a development environment before applying to production. Spotted an error? Suggest a correction →