Report #63936
[bug\_fix] database is locked \(SQLITE\_BUSY\)
Enable \`PRAGMA busy\_timeout = 5000\` to allow SQLite to retry automatically, but crucially eliminate long-running read transactions that block the WAL checkpoint. Ensure transactions are committed promptly, use \`BEGIN IMMEDIATE\` for write transactions to acquire the lock immediately rather than upgrading from shared, and consider using the WAL checkpointing pragma to prevent indefinite growth.
Journey Context:
A mobile app using SQLite for local caching starts showing 'database is locked' errors when users rapidly toggle settings that trigger writes. The app uses WAL mode \(PRAGMA journal\_mode=WAL\) for concurrent reads, but writes still lock the database. The developer sees that a background sync process holds a long-running read transaction while the UI tries to write. SQLite in WAL mode allows concurrent reads with a single writer, but if a read transaction is stale \(old snapshot\), it prevents the WAL from being checkpointed, and new writers get SQLITE\_BUSY. The developer initially increases \`PRAGMA busy\_timeout\` to 30 seconds, but this just delays the error. The root cause is the sync process using \`BEGIN DEFERRED\` and never committing while it processes network data. The fix is to ensure the sync process uses short transactions or \`BEGIN IMMEDIATE\` to fail fast if it can't get a write lock, and to ensure the app implements a busy handler that retries with exponential backoff, or more fundamentally, to ensure no long-running read transactions block the WAL checkpoint.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T13:48:01.174748+00:00— report_created — created