sqlite3.OperationalError: database is locked
Python · updated 2026-11-04
Raised when a connection waits longer than its timeout (5 seconds by default in Python) for another connection to release the write lock. SQLite allows one writer at a time, so long transactions or several processes writing the same file trigger it.
Traceback (most recent call last):
File "/app/worker.py", line 44, in save_result
conn.execute("INSERT INTO results (job_id, payload) VALUES (?, ?)", (job_id, payload))
sqlite3.OperationalError: database is lockedQuick fix
Enable WAL mode (PRAGMA journal_mode=WAL) so readers don't block the writer, raise the timeout (sqlite3.connect(path, timeout=30)), and keep write transactions short: commit right after writing, and never hold a transaction open across slow work like network calls.
- Set PRAGMA journal_mode=WAL once on the database file (it persists).
- Open connections with a longer timeout, or set PRAGMA busy_timeout=30000.
- Commit promptly; do slow work (HTTP calls, file processing) before or after the transaction, not inside it.
- Look for a forgotten open transaction: a connection that executed a write and never committed.
- If many processes write constantly, consider a server database (Postgres) instead.
import sqlite3
conn = sqlite3.connect("/data/app.db", timeout=30) # wait up to 30 s for the lock
conn.execute("PRAGMA journal_mode=WAL") # readers no longer block the writer
conn.execute("PRAGMA busy_timeout=30000")
payload = fetch_payload(job_id) # slow work outside the transaction
with conn: # short write, committed on exit
conn.execute("INSERT INTO results (job_id, payload) VALUES (?, ?)", (job_id, payload))Why it happens
Several processes writing the same file
Web workers, background jobs and cron scripts all writing one SQLite file contend for the single write lock.
Long or forgotten transactions
A connection that starts a write and then does slow work, or never commits, holds the lock and makes every other writer wait.
The default rollback journal
Without WAL, a reader can block a writer and the writer blocks readers, so busy apps lock up far more often.
Network file systems
SQLite locking is unreliable on NFS and some container volume drivers, which can produce locks that never clear.
Other fixes
- Run backups with the online backup API or sqlite3 .backup instead of copying the file while it is in use.
- In Django, set OPTIONS {"timeout": 30} for the SQLite database and keep long jobs out of request handlers.
Same error, other wording
- sqlite3.OperationalError: database is locked (Django)
- SqliteError: database is locked
- sqlite3.OperationalError: database table is locked
Let your coding agent catch the next one
Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:
> Find the 'database is locked' errors in production, show me which processes write the SQLite file and how long their transactions stay open, and turn on WAL, raise the busy timeout and shorten the transactions.
Related errors
- sqlalchemy.exc.PendingRollbackError: This Session's transaction has been rolled back due...
- django.db.utils.OperationalError: no such table: orders_order
- psycopg.errors.UniqueViolation: duplicate key value violates unique constraint...
References: SQLite docs: write-ahead logging, Python docs: sqlite3.connect (timeout)