Report #24895
[bug\_fix] Database disk image is malformed \(SQLITE\_CORRUPT\)
SQLite database corruption on network filesystems \(NFS, SMB\) occurs because SQLite relies on POSIX advisory locking \(fcntl\) to coordinate access between processes. Network filesystems often implement locking incorrectly or with delays, allowing two processes to simultaneously hold exclusive locks. This causes race conditions where one process overwrites another's journal or data page. The fix is to NEVER store SQLite database files on a network filesystem if multiple hosts access it. Move the database to a local filesystem \(ext4, XFS, NTFS\). If multi-host access is required, migrate to a client/server database \(PostgreSQL\). For single-host with network backup, copy the file to the network, don't access it live.
Journey Context:
A small business runs a legacy Python application using SQLite, storing the .db file on an NFS share at /mnt/nfs/shared/data.db so that two office computers can access it 'simultaneously'. Intermittently, queries return 'database disk image is malformed', and PRAGMA integrity\_check reports 'row 456 missing from index idx\_foo'. They restore from backup, but corruption recurs weekly. The developer suspects SQLite bugs and tries different journal modes. Eventually, they trace the corruption to times when both PC-A and PC-B perform writes concurrently. Investigating SQLite's 'How To Corrupt Your Database File' page, they find the section explicitly warning about NFS: 'POSIX locking is known to be broken or unimplemented on many NFS implementations.' They realize NFS client-side caching and broken fcntl locking allow both PCs to think they have exclusive locks, causing write interleaving. The definitive solution is migrating the application to PostgreSQL running on a central server, since true multi-host concurrent write access is an anti-pattern for SQLite. They verify the fix by moving the DB to a local ext4 drive on one PC \(with the other PC accessing via a proper client-server API\), and the corruption stops permanently.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T20:11:39.076566+00:00— report_created — created