SQLite: cannot commit - no transaction is active (tested)

sqlite3.OperationalError: cannot commit - no transaction is active only shows up from raw SQL, never from Python's own commit() method. We measured exactly where that split happens.

1. Python's con.commit() silently does nothing

With no transaction open at all, we called the high-level method directly:

con = sqlite3.connect("m1.db")
con.commit()     # no error
con.rollback()   # no error

Measured: both are silent no-ops. Nothing raises, nothing is logged — this is by design in Python's sqlite3 wrapper, not a bug.

2. The raw SQL statement raises, for the identical state

Same connection, same "nothing is open" state, but issuing the SQL statement directly instead of calling the method:

con.execute("COMMIT")
sqlite3.OperationalError: cannot commit - no transaction is active

con.execute("ROLLBACK")
sqlite3.OperationalError: cannot rollback - no transaction is active

The split, measured directly: con.commit()/con.rollback() are Python-level convenience methods that check the connection's own transaction state first and quietly skip the SQL entirely if nothing is open. con.execute("COMMIT") sends the literal SQL straight to SQLite, which has no such check built in — it just fails. The two aren't interchangeable, even though they look like they do the same thing.

3. The fix: use the Python methods, or check first

If you're issuing COMMIT/ROLLBACK as raw SQL (common when porting code from another DB-API or writing cross-database SQL), guard it:

if con.in_transaction:
    con.execute("COMMIT")

Or simply switch to con.commit()/con.rollback(), which we confirmed handle the "nothing to commit" case safely with zero extra code.

Frequently asked questions

Why does con.commit() not raise this error, but raw SQL COMMIT does?

We measured both directly: con.commit() checks the connection's transaction state first and silently no-ops if nothing is open. con.execute('COMMIT') sends the literal SQL straight through with no such check, so it fails against SQLite's own rule that COMMIT requires an active transaction.

Is con.rollback() with nothing open also silent?

Yes — we confirmed it's a no-op identical to con.commit(), while con.execute('ROLLBACK') against the same empty state raises 'cannot rollback - no transaction is active'.

When would raw SQL COMMIT/ROLLBACK show up in real code instead of the Python methods?

Code ported from another database's DB-API, or a cross-database SQL layer that issues the same statement text regardless of backend — we reproduced the error specifically from the raw-SQL path, not from any use of Python's own transaction methods.

How do I guard raw SQL COMMIT so it doesn't fail?

Check con.in_transaction before issuing it — we confirmed this reports the connection's real state and lets you skip the COMMIT entirely when nothing is open, avoiding the error with no behavior change.

Does this affect BEGIN too?

That's the reverse problem — see our cannot-start-a-transaction-within-a-transaction guide for what happens when BEGIN runs while one is already open, which is a different mismatch than the one measured here.

Written with AI assistance. Measured on 2026-10-03 with Python 3.13.5's built-in sqlite3 module, comparing the high-level con.commit()/con.rollback() methods against raw SQL COMMIT/ROLLBACK statements with no transaction open. Every result below is copy-pasted output, not paraphrased. PlainHeaders is our extension; Python's sqlite3 is built in.