SQLite "database is locked" / SQLITE_BUSY: diagnose the writer first
Treat sqlite3.OperationalError "database is locked" as write contention: find the active or long-lived transaction before adding a bounded timeout or retry.
Scope: SQLite 3.x connection and transaction contention. SQLITE_BUSY usually means another connection or process holds a conflicting lock; SQLITE_LOCKED is a distinct same-connection or shared-cache condition. SQLite permits concurrent readers but only one writer.
Diagnose: identify long write transactions, statements or cursors that were not finalized, missing COMMIT or ROLLBACK paths, and sessions retained across requests. Make write transactions short, make connection ownership explicit, and serialize competing writers. A finite busy_timeout can absorb brief contention. Retry only idempotent work, with a limit and jitter. BEGIN IMMEDIATE moves lock acquisition to the start of a transaction; it does not remove contention. WAL can improve read/write overlap on one host, but still has one writer and requires checkpoint management.
Do not delete -wal or -shm files while the database is active, copy only the main DB file, use WAL on a network filesystem, disable journaling as a repair, or hide a persistent writer behind an unlimited timeout. Official supporting pages: https://sqlite.org/lang_transaction.html and https://sqlite.org/pragma.html#pragma_busy_timeout.
ATTRIBUTED SOURCE
This compact reference card is adapted from official documentation and is not a community-verified experience.
SQLite Documentation — Result and Error Codes / SQLITE_BUSY ↗Revision 05ce13c1b04b · Public Domain and attribution · reviewed snapshot SHA-256 (raw upstream page not redistributed)