{"record":{"id":"9da07d2b30d97b80","repo":"tursodatabase/turso","slug":"transactions-must-overlap-before-queries-start","errorCode":null,"errorMessage":"transactions must overlap before queries start","messagePattern":"transactions must overlap before queries start","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"perf/memory/src/fts.rs","lineNumber":208,"sourceCode":"        observer.on_phase(FtsPhase::Done);\n    }\n\n    async fn batch(&self, queries: usize) -> Result<RunResult> {\n        let transactions = matches!(self.config.execution, Execution::Transactions { .. });\n        let outcome = async {\n            let mut active = 0;\n            if transactions {\n                let begin = match self.config.mode {\n                    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        }","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/tursodatabase/turso/blob/492c4a71cd7c2649e7df83da1471b74f4b1c7aa9/perf/memory/src/fts.rs#L190-L226","documentation":"The benchmark's batch runner begins a transaction on every session and then verifies that all sessions actually report an active (non-autocommit) transaction before running queries. If any connection is still in autocommit mode, the concurrent-transaction memory measurement would be invalid, so it fails with this error.","triggerScenarios":"Calling batch() with transactions enabled after a session's begin() silently failed to start a transaction — e.g. the BEGIN statement was a no-op, was rolled back, or the connection already committed internally.","commonSituations":"Driver/connection returns Ok from begin() but is_autocommit() still true due to a driver bug or unsupported transaction mode; running against a backend that ignores BEGIN; sessions were reused after an earlier error left them in autocommit.","solutions":["Check each session's begin() result and is_autocommit() state immediately after BEGIN to find the offending connection","Ensure the connections/driver version supports explicit transactions","Reset or reopen sessions before each batch so no stale autocommit state remains"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for session in &self.sessions {\n    session.begin(begin).await?;\n    if session.conn.is_autocommit()? {\n        return Err(anyhow!(\"session failed to enter a transaction\"));\n    }\n}","typeGuard":null,"tryCatchPattern":"match batch_result {\n    Err(e) if e.to_string().contains(\"transactions must overlap\") => {\n        // inspect per-session autocommit state, recreate sessions, retry\n    }\n    r => r?,\n}","preventionTips":["Verify is_autocommit() right after BEGIN in your own harness","Use fresh sessions per batch to avoid stale transaction state","Keep driver and library versions in sync"],"tags":["benchmark","transactions","invariant","fts"],"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-14T00:17:10.932Z"}