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 locked

Quick 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.

  1. Set PRAGMA journal_mode=WAL once on the database file (it persists).
  2. Open connections with a longer timeout, or set PRAGMA busy_timeout=30000.
  3. Commit promptly; do slow work (HTTP calls, file processing) before or after the transaction, not inside it.
  4. Look for a forgotten open transaction: a connection that executed a write and never committed.
  5. If many processes write constantly, consider a server database (Postgres) instead.
python
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.

Plans from $29/moSee what your agent readsSee the setupCancel any time from the billing portal

Related errors

References: SQLite docs: write-ahead logging, Python docs: sqlite3.connect (timeout)