{"record":{"id":"1a40da9dc5204498","repo":"tursodatabase/turso","slug":"commit-must-end-the-transaction","errorCode":null,"errorMessage":"COMMIT must end the transaction","messagePattern":"COMMIT must end the transaction","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"perf/memory/src/fts.rs","lineNumber":217,"sourceCode":"                    JournalMode::Wal => \"BEGIN\",\n                    JournalMode::Mvcc => \"BEGIN CONCURRENT\",\n                };\n                for session in &self.sessions {\n                    session.begin(begin).await?;\n                }\n                for session in &self.sessions {\n                    active += usize::from(!session.conn.is_autocommit()?);\n                }\n                ensure!(\n                    active == self.sessions.len(),\n                    \"transactions must overlap before queries start\"\n                );\n            }\n            let mut result = self.query_all(queries).await?;\n            if transactions {\n                for session in &self.sessions {\n                    session.commit().await?;\n                    ensure!(\n                        session.conn.is_autocommit()?,\n                        \"COMMIT must end the transaction\"\n                    );\n                }\n                result.transactions = self.sessions.len();\n                result.max_active_transactions = active;\n            }\n            Ok(result)\n        }\n        .await;\n        if outcome.is_err() {\n            for session in &self.sessions {\n                if !session.conn.is_autocommit()? {\n                    session.conn.execute(\"ROLLBACK\", ()).await?;\n                }\n            }\n        }\n        outcome","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/tursodatabase/turso/blob/492c4a71cd7c2649e7df83da1471b74f4b1c7aa9/perf/memory/src/fts.rs#L199-L235","documentation":"After issuing COMMIT on each session, the batch runner asserts the connection is back in autocommit mode. If is_autocommit() is still false after commit(), the transaction did not actually end, invalidating the measurement and possibly leaving the connection in a broken state, so the benchmark aborts.","triggerScenarios":"Calling session.commit() during a transactional batch when COMMIT is ignored, fails silently, or the connection starts a new implicit transaction immediately, leaving is_autocommit() false.","commonSituations":"Driver-level commit bug; nested/deferred transactions that don't fully release on COMMIT; a statement inside the transaction opened a new transaction after commit; connection in a broken state after an earlier query error.","solutions":["Log is_autocommit() before and after commit() on each session to isolate the connection that fails to end its transaction","Check the query_all() results for errors that may have aborted the commit path","Verify the driver version handles COMMIT correctly; recreate the session if state is corrupted"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"session.commit().await?;\nif !session.conn.is_autocommit()? {\n    return Err(anyhow!(\"session still in transaction after COMMIT\"));\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = batch.run().await {\n    if e.to_string().contains(\"COMMIT must end\") {\n        // force rollback / recreate session before continuing\n    }\n}","preventionTips":["Check for errors in queries inside the transaction before committing","Avoid nested transaction attempts on a single connection","Recreate sessions that survive an earlier error"],"tags":["benchmark","transactions","commit","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"492c4a71cd7c2649e7df83da1471b74f4b1c7aa9","analyzedAt":"2026-09-13T18:13:59.796Z","contentChangedAt":"2026-09-13T18:13:59.796Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}