tursodatabase/turso · error · InvalidOperationException
A transaction is already active on this connection.
Error message
A transaction is already active on this connection.
What it means
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.
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
Example fix
// before
var tx1 = conn.BeginTransaction();
var tx2 = conn.BeginTransaction(); // throws: already active
// after
using (var tx = conn.BeginTransaction())
{
// all work, including nested helper calls, joins tx
tx.Commit();
} Defensive patterns
Strategy: validation
Validate before calling
// one transaction per connection at a time -- serialize access
await _connectionGate.WaitAsync();
try
{
using var tx = conn.BeginTransaction();
/* work */ tx.Commit();
}
finally { _connectionGate.Release(); } Type guard
static bool SupportsNestedTransactions => false;
Try / catch
try { var tx = conn.BeginTransaction(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already active"))
{
// commit/rollback the existing transaction first, or use a separate connection
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No remote transaction is active on this connection.
- Auth Token requires a remote Turso URL Data Source.
- Embedded replica connections are not supported yet by the…
- Embedded replica sync is not supported yet by the .NET…
- Encryption Cipher and Encryption Key are local database…
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-09-06).
Data as JSON: /api/errors/a2bd6ce12749974f.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/dotnet/src/Turso.Data/TursoConnection.cs:351
if (_remoteTransactionActive)
InvalidateRemoteSession();
else
remoteClient.ResetSession();
}
throw;
}
catch
{
InvalidateRemoteSession();
throw;
}
}
internal void BeginRemoteTransaction(IsolationLevel isolationLevel, bool deferred = true)
{
var remoteClient = _remoteClient ?? throw new InvalidOperationException("Turso database is closed.");
if (_remoteTransactionActive)
throw new InvalidOperationException("A transaction is already active on this connection.");
_remoteTransactionFailure = null;
_remoteTransactionActive = true;
try
{
remoteClient
.ExecuteAsync(
isolationLevel == IsolationLevel.Serializable && !deferred
? "BEGIN IMMEDIATE"
: "BEGIN",
new TursoParameterCollection(),
wantRows: false,
DefaultTimeout,
closeAfter: false,
CancellationToken.None)
.GetAwaiter()
.GetResult();
}View on GitHub (pinned to 6c72522679)