SQLITE_LOCKED
SQLiteERRORNotableLocking & ConcurrencyHIGH confidence

database table is locked

What this means

SQLITE_LOCKED (result code 6) is a finer-grained lock conflict than SQLITE_BUSY. It occurs when a specific database object (typically a table) is locked within the same database connection — most commonly when trying to write to a table that a still-open cursor is iterating over, or when a savepoint conflict arises within a single connection.

Why it happens
  1. 1A cursor is still iterating over a SELECT result while a write to the same table is attempted on the same connection
  2. 2An open statement on the connection holds a shared lock on the table being written
  3. 3Shared-cache mode is enabled and two different connections in the same process conflict at the table level
How to reproduce

A cursor over a table is still open when an UPDATE on the same table is attempted on the same connection.

trigger — this will error
trigger — this will error
import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE t (x INTEGER)')
conn.executemany('INSERT INTO t VALUES (?)', [(i,) for i in range(5)])

cursor = conn.execute('SELECT x FROM t')
conn.execute('UPDATE t SET x = x + 1')  # triggers SQLITE_LOCKED

expected output

sqlite3.OperationalError: database table is locked

Fix

Fetch all rows before writing

WHEN When you need to iterate and then update the same table.

Fetch all rows before writing
import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE t (x INTEGER)')
conn.executemany('INSERT INTO t VALUES (?)', [(i,) for i in range(5)])

rows = conn.execute('SELECT x FROM t').fetchall()  # materialise first
conn.execute('UPDATE t SET x = x + 1')             # now safe

Why this works

fetchall() forces the statement to read all rows from the B-tree into memory and closes the cursor. With no open read cursor the connection can safely escalate to a write lock on the table.

What not to do

Enable shared-cache mode to "improve performance"

Shared-cache mode increases the likelihood of SQLITE_LOCKED errors because table-level locks become visible across connections in the same process.

Version notes
SQLite 3.6.19+

Extended result code SQLITE_LOCKED_SHAREDCACHE (262) added to distinguish shared-cache conflicts from same-connection conflicts.

Sources

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All SQLite errors