Quick answer
Kill the process holding the lock, force close the connection, or switch to WAL mode to reduce lock contention.
Why this happens
SQLite is a lightweight database – it locks the whole file when writing. This error shows up when another program (or thread) has an open transaction and didn't close it cleanly. I saw this last month with a small accounting app where the user force-quit the program during a bank import. The lock file stayed, and the app couldn't open the database again until we cleared it.
Common triggers:
- Two instances of the same app running
- A crash during a write operation
- A shared database on a network drive (bad idea, but people do it)
- A long-running transaction that wasn't committed or rolled back
Fix steps
Step 1: Check for other processes using the database file
On Windows, use Process Explorer or task manager. Look for processes that have the database file open. On Linux or macOS, run:
lsof /path/to/your/database.db
If you see a process ID, kill it:
kill -9 <PID>
On Windows, use:
handle.exe -a -u database.db
(handle.exe is from Sysinternals)
Step 2: Close all connections in your code
Make sure you close each connection properly. In Python, use context managers:
import sqlite3
with sqlite3.connect('mydb.db') as conn:
cursor = conn.cursor()
cursor.execute('SELECT 1')
conn.commit()
# Connection closes automatically
If you forget conn.close(), the lock stays until the Python process dies.
Step 3: Delete the journal or WAL file
If the database crashed, leftover files like database.db-journal or database.db-wal can cause locks. Delete them only after you've confirmed no process is using the database. Backup first.
rm -f /path/to/database.db-journal
rm -f /path/to/database.db-wal
Step 4: Reboot if nothing works
Seriously. Reboot clears all locks. It's not elegant, but it fixes 90% of cases.
Alternative fixes if main one fails
Use WAL mode (Write-Ahead Logging)
WAL mode allows concurrent reads and writes. It reduces lock contention. Change it once:
PRAGMA journal_mode=WAL;
Had a client whose small CRM app stored everything in SQLite. After switching to WAL, the locked errors almost disappeared. But note: WAL files can grow large if not checkpointed regularly. Use PRAGMA wal_checkpoint(TRUNCATE); periodically.
Set a busy timeout
Instead of failing immediately, SQLite can wait for a lock:
PRAGMA busy_timeout = 5000; -- wait 5 seconds
Set this at the start of each connection. It helps when the lock is temporary.
Use a connection pool
If multiple parts of your app access the database, use a single connection pool. Python's sqlite3 module doesn't have a built-in pool, but you can use queue.Queue or third-party libraries like SQLAlchemy.
Prevention tips
- Always close connections – use
withblocks ortry/finally. - Use transactions explicitly – don't leave them open.
- Enable WAL mode – it's the single best change you can make.
- Don't share the database over a network drive – SQLite isn't designed for that. Use a proper server database like PostgreSQL or MariaDB if you need multiple machines writing.
- Monitor for hanging processes – set up a cron job to kill old connections if the app crashes often.
One more thing: if this happens a lot, it's a sign of bad code. Check for unclosedcursorobjects, missedconn.commit()calls, or long-running SELECT statements that block writes.
That's it. Fix the lock, move on. You don't need to overcomplicate it.