Report #5272
[bug\_fix] sqlite3.OperationalError: cannot start a transaction within a transaction
Replace the use of BEGIN/COMMIT/ROLLBACK for nested transaction logic with SQLite SAVEPOINTs; when entering a nested transactional context, execute "SAVEPOINT savepoint\_name" instead of "BEGIN", on success execute "RELEASE SAVEPOINT savepoint\_name", and on failure execute "ROLLBACK TO SAVEPOINT savepoint\_name" to undo the nested changes without affecting the outer transaction.
Journey Context:
A Python desktop application using the sqlite3 module implements a @transaction decorator that executes BEGIN DEFERRED when entering a function and COMMIT on success or ROLLBACK on exception. A service method decorated with @transaction calls a helper method that also uses the @transaction decorator. When the code runs, it raises "sqlite3.OperationalError: cannot start a transaction within a transaction". Investigation reveals that SQLite does not support true nested transactions; once a transaction is started with BEGIN, subsequent BEGIN statements fail with this error. The developer initially tries to check if already in a transaction using sqlite3.get\_autocommit\(\), but finds managing state manually is error-prone. Researching the SQLite documentation reveals that while nested transactions are not supported, SAVEPOINTs provide equivalent functionality. The developer refactors the @transaction decorator to track nesting depth. When depth is 0, it uses BEGIN/COMMIT/ROLLBACK as before. When depth > 0, it generates a unique savepoint name \(e.g., "savepoint\_1"\), executes "SAVEPOINT savepoint\_1" on entry, "RELEASE SAVEPOINT savepoint\_1" on success, and "ROLLBACK TO SAVEPOINT savepoint\_1" on exception. This allows the inner method to undo its changes if it fails without affecting the outer transaction's work. The error disappears and the application can safely nest transactional operations.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-15T20:56:41.085152+00:00— report_created — created