{"record":{"id":"a2bd6ce12749974f","repo":"tursodatabase/turso","slug":"a-transaction-is-already-active-on-this-connection","errorCode":null,"errorMessage":"A transaction is already active on this connection.","messagePattern":"A transaction is already active on this connection\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoConnection.cs","lineNumber":236,"sourceCode":"                .ConfigureAwait(false);\n        }\n        catch (TursoRemoteSqlException)\n        {\n            throw;\n        }\n        catch\n        {\n            InvalidateRemoteSession();\n            throw;\n        }\n    }\n\n    internal void BeginRemoteTransaction(IsolationLevel isolationLevel)\n    {\n        _ = isolationLevel;\n        var remoteClient = _remoteClient ?? throw new InvalidOperationException(\"Turso database is closed.\");\n        if (_remoteTransactionActive)\n            throw new InvalidOperationException(\"A transaction is already active on this connection.\");\n\n        _remoteTransactionActive = true;\n        try\n        {\n            remoteClient\n                .ExecuteAsync(\"BEGIN\", new TursoParameterCollection(), wantRows: false, DefaultTimeout, closeAfter: false, CancellationToken.None)\n                .GetAwaiter()\n                .GetResult();\n        }\n        catch (TursoRemoteSqlException)\n        {\n            _remoteTransactionActive = false;\n            throw;\n        }\n        catch\n        {\n            InvalidateRemoteSession();\n            throw;","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/dotnet/src/Turso.Data/TursoConnection.cs#L218-L254","documentation":"BeginRemoteTransaction tracks one _remoteTransactionActive flag per connection and refuses a second BEGIN with 'A transaction is already active on this connection.' The remote path supports at most one outstanding transaction per connection: no nested transactions and no concurrent ones on a shared connection.","triggerScenarios":"Calling connection.BeginTransaction() twice without Commit/Rollback in between; two threads or requests sharing one connection each calling BeginTransaction; repository methods that each wrap their work in a transaction and call each other.","commonSituations":"Recursive service methods with [Transactional]-style wrappers; a pooled connection reused by concurrent requests that both begin transactions; a missing commit in an error path leaving the transaction open.","solutions":["Commit or Rollback the existing TursoTransaction before beginning another on the same connection","Use one connection per concurrent transaction; never share a TursoConnection across threads for transactional work","Restructure nested 'transactional' methods to accept an optional existing transaction instead of always opening a new one"],"exampleFix":"// before\nvar tx1 = conn.BeginTransaction();\nvar tx2 = conn.BeginTransaction(); // throws: already active\n\n// after\nusing (var tx = conn.BeginTransaction())\n{\n    // all work, including nested helper calls, joins tx\n    tx.Commit();\n}","handlingStrategy":"validation","validationCode":"// one transaction per connection at a time -- serialize access\nawait _connectionGate.WaitAsync();\ntry\n{\n    using var tx = conn.BeginTransaction();\n    /* work */ tx.Commit();\n}\nfinally { _connectionGate.Release(); }","typeGuard":"static bool SupportsNestedTransactions => false;","tryCatchPattern":"try { var tx = conn.BeginTransaction(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already active\"))\n{\n    // commit/rollback the existing transaction first, or use a separate connection\n}","preventionTips":["Commit or Rollback before beginning another transaction on the same connection","Never share one connection between concurrent transactions","Pass an optional ambient transaction into nested methods instead of opening a new one"],"tags":["csharp","dotnet","turso","transactions","concurrency"],"backgroundTag":"transaction-already-active","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}