Report #58094
[bug\_fix] SQLite attempt to write a readonly database
Ensure the directory containing the database file \(not just the file itself\) is writable by the process, remove stale WAL \(-wal\) and SHM \(-shm\) files from previous runs with different UIDs, and verify the underlying filesystem is not mounted read-only.
Journey Context:
A Python Flask application running inside a Docker container \(Alpine Linux\) with the SQLite database file mounted from the host via a bind volume began crashing with sqlite3.OperationalError: attempt to write a readonly database immediately upon any INSERT or UPDATE operation. The developer first checked the file permissions inside the container: ls -l /app/data/ showed -rw-r--r-- 1 1000 1000 1048576 db.sqlite3, indicating the file was owned by UID 1000 \(matching the host user\) and was writable by the owner. However, the container was running as the root user \(UID 0\), which should still have been able to write. The developer then checked for the presence of WAL files and discovered a stale db.sqlite3-wal and db.sqlite3-shm file in the directory, owned by root \(UID 0\) from a previous container run that had crashed. SQLite in WAL mode requires write access to these files. Because the current process \(running as UID 1000 via --user flag in the new deployment\) did not own these WAL files and could not write to them, and because SQLite requires write access to the directory to create new journal files if WAL were disabled, the write failed. The fix involved removing the stale WAL and SHM files \(which are safe to delete if the database was cleanly closed, or running PRAGMA wal\_checkpoint to merge them first\), ensuring the directory /app/data/ was writable by the container user \(not just the file\), and consistently running the container with --user $\(id -u\):$\(id -g\) to match the host filesystem permissions and prevent UID mismatches that leave orphaned WAL files.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T04:00:04.161831+00:00— report_created — created