Report #69222
[bug\_fix] database is locked \(SQLITE\_BUSY\) in WAL mode
Set \`PRAGMA busy\_timeout = 5000\` \(milliseconds\) on all connections to enable automatic retry, and ensure no long-running read transactions block the writer by committing reads immediately.
Journey Context:
A developer ships an Electron-based desktop analytics tool using SQLite in WAL mode for concurrent reads and writes. Users report intermittent "database is locked" errors when the app tries to save settings while a background analytics query runs. The developer initially implements a retry loop in JavaScript using \`setTimeout\`, but the timing is unreliable and users still see failures. They investigate SQLite behavior and learn that in WAL mode, readers do not block writers and writers do not block readers, but only one writer can be active at a time. If a second writer tries to commit while the first is still writing, or if a checkpoint is in progress, SQLITE\_BUSY is returned immediately unless busy handling is configured. They modify the database initialization code to execute \`PRAGMA busy\_timeout = 10000\` immediately after opening each connection. This causes SQLite to internally retry busy locks with exponential backoff up to 10 seconds rather than returning SQLITE\_BUSY immediately. They also refactor the background analytics to use \`db.prepare\(\).all\(\)\` and immediately close the statement rather than holding a long-lived connection. After this, "database is locked" errors disappear because the busy timeout handles transient contention, and shorter transactions reduce the contention window.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T22:40:33.931413+00:00— report_created — created