Download

cannot start a transaction within a transaction

You ran BEGIN while a transaction was already open on the connection, often one your driver began for you. SQLite transactions don’t nest: commit the open one first, or use SAVEPOINT for an inner transaction.

SQLite error SQLITE_ERROR· Tested on SQLite 3.51.0 (macOS /usr/bin/sqlite3)· Updated 11 October 2026

cannot start a transaction within a transaction

What it means

A connection has at most one transaction open at a time, and SQLite’s BEGIN … COMMIT transactions don’t nest. Running BEGIN while one is open fails with SQLITE_ERROR (code 1) and cannot start a transaction within a transaction. The open transaction carries on unaffected.

Two related messages mean the opposite mismatch, COMMIT or ROLLBACK with nothing open:

  • cannot commit - no transaction is active
  • cannot rollback - no transaction is active

And VACUUM refuses to run inside a transaction: cannot VACUUM from within a transaction.

In each case, your code’s idea of whether a transaction is open differs from the connection’s.

Common causes

  1. Your driver already began one. Python’s sqlite3 module, by default, opens a transaction by itself before the first INSERT, UPDATE, DELETE or REPLACE; an explicit BEGIN after that fails. With autocommit=False (Python 3.12 and later), a transaction is always open.
  2. Nested code. A function that runs BEGIN is called from code that already began a transaction.
  3. A transaction left open. An error path skipped COMMIT or ROLLBACK, and the next BEGIN on that connection, perhaps from a pool, fails.
  4. The transaction already ended. The driver committed for you, an earlier COMMIT ran twice, or SQLite rolled back because of an error: an INSERT OR ROLLBACK (or ON CONFLICT ROLLBACK) conflict always does, and SQLITE_FULL, SQLITE_IOERR, SQLITE_INTERRUPT and SQLITE_NOMEM errors can. The COMMIT then has nothing to commit.
  5. VACUUM in a transaction: a migration tool that wraps every step in a transaction, or Python code that wrote something and hasn’t committed yet.

How to fix it

Ask the connection

In C, sqlite3_get_autocommit(db) returns non-zero when no transaction is open. In Python, connection.in_transaction is True while one is. Check it where the error occurs rather than guessing.

Let the driver handle it, or take it over completely

With Python’s sqlite3, either don’t run BEGIN at all and let the module manage transactions (with connection: commits on success and rolls back on an exception), or turn its handling off and issue every BEGIN and COMMIT yourself:

connection = sqlite3.connect("app.db", autocommit=True)  # Python 3.12+; isolation_level=None before
connection.execute("BEGIN IMMEDIATE")
# …
connection.execute("COMMIT")

Mixing the two is what produces this error. Other drivers and ORMs have the same choice; check whether yours begins transactions for you.

Use savepoints for inner transactions

Savepoints nest, inside a transaction or on their own:

BEGIN;
SAVEPOINT import_batch;
INSERT INTO t VALUES (2);
RELEASE import_batch;        -- or ROLLBACK TO import_batch to undo only this part
COMMIT;

A helper that might be called inside a transaction should use SAVEPOINT and RELEASE instead of BEGIN and COMMIT.

Always finish what you begin

Put ROLLBACK in the error path (try/finally, defer), so a failure doesn’t leave the connection mid-transaction for the next caller.

After “no transaction is active”, check what was saved

If an error came first, SQLite may have rolled back the whole transaction, so earlier statements are gone too. Redo the work rather than assuming it’s committed. After SQLITE_FULL or SQLITE_IOERR, issuing ROLLBACK yourself is safe: it fails harmlessly if SQLite already rolled back.

Run VACUUM on its own

Commit first, then run VACUUM outside any transaction. In Python, call connection.commit() before connection.execute("VACUUM"), or use a connection with autocommit=True.

Reproduce it

macOS /usr/bin/sqlite3, SQLite 3.51.0:

sqlite3 tx.db "BEGIN; INSERT INTO t VALUES (1); BEGIN;"
Error: stepping, cannot start a transaction within a transaction

The shell adds “Error: stepping,”; SQLite’s message is cannot start a transaction within a transaction. Run as a script, the first transaction carried on after the failed BEGIN: another insert and a COMMIT saved both rows. With no transaction open, COMMIT, ROLLBACK and END gave:

Error: stepping, cannot commit - no transaction is active
Error: stepping, cannot rollback - no transaction is active
Error: stepping, cannot commit - no transaction is active

A transaction ended by a conflict: BEGIN, an insert, then an INSERT OR ROLLBACK that broke a unique constraint, then COMMIT:

Runtime error near line 3: UNIQUE constraint failed: u.x (19)
Runtime error near line 4: cannot commit - no transaction is active

The first insert was gone. With a plain INSERT in place of INSERT OR ROLLBACK, the same conflict left the transaction open, and COMMIT saved the first insert. VACUUM after BEGIN:

Runtime error near line 2: cannot VACUUM from within a transaction

Python 3.14’s sqlite3 module (SQLite 3.53.4), default settings: after connection.execute("INSERT …"), in_transaction was True, and connection.execute("BEGIN") raised sqlite3.OperationalError: cannot start a transaction within a transaction. VACUUM at the same point raised cannot VACUUM from within a transaction. On a connection opened with autocommit=False, the first BEGIN failed the same way.

In Inlet

Grid edits are staged until you commit (⌘S) and then go in as one transaction. In the query editor, with manual commit, finish each transaction with COMMIT or ROLLBACK before you begin another.

Inlet: a database client for the Mac

One native app for PostgreSQL, MySQL, SQL Server, SQLite, MongoDB and Redis. It explains errors where they happen, holds your edits until you save them, and keeps production read-only until you say so.

Version 0.1.0 · macOS 26 Tahoe or later · Apple silicon and Intel