tursodatabase/turso · error · InvalidOperationException
Turso sync connection ownership is unbalanced.
Error message
Turso sync connection ownership is unbalanced.
What it means
TursoSyncDatabase tracks connection ownership with an atomic counter (_activeConnections). ReleaseConnection() decrements it and throws InvalidOperationException if the count would go negative, which indicates a bug: a Release without a matching Connect — an internal bookkeeping invariant violation rather than a user configuration problem.
Source
Thrown at bindings/dotnet/src/Turso.Data/TursoSyncDatabase.cs:315
TursoSyncOperationKind.Connect,
cancellationToken)
.ConfigureAwait(false);
EnsureResultKind(operation, TursoSyncOperationResultKind.Connection);
var connectionHandle = TursoSyncBindings.ExtractConnection(_handle, operation);
Interlocked.Increment(ref _activeConnections);
return connectionHandle;
}
finally
{
_operationLock.Release();
}
}
internal void ReleaseConnection()
{
var remaining = Interlocked.Decrement(ref _activeConnections);
if (remaining < 0)
throw new InvalidOperationException("Turso sync connection ownership is unbalanced.");
if (remaining == 0 && Volatile.Read(ref _disposeRequested) != 0)
DisposeResources();
}
private async Task RunVoidOperationAsync(
Func<TursoSyncDatabaseHandle, TursoSyncOperationHandle> start,
TursoSyncOperationKind operationKind,
CancellationToken cancellationToken)
{
ThrowIfDisposed();
await _operationLock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
ThrowIfDisposed();
using var operation = StartOperation(start, operationKind);
await DriveOperationAsync(operation, operationKind, cancellationToken).ConfigureAwait(false);
EnsureResultKind(operation, TursoSyncOperationResultKind.None);
}View on GitHub (pinned to 6c72522679)
Solutions
- Check custom code for duplicate ReleaseConnection() calls or calling it without a prior successful Connect.
- Ensure Dispose is not racing concurrent Connect/Release calls; serialize disposal with connection lifecycle.
- If reproducible, report as a driver bug with a stack trace — this is an internal invariant violation.
Defensive patterns
Strategy: try-catch
Try / catch
try
{
connection.Close();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("ownership is unbalanced"))
{
_logger.LogError(ex, "Driver bug: unbalanced connection ownership. Report with stack trace.");
} Prevention
- Never call internal Release-style APIs more than once per successful connect.
- Serialize Dispose with concurrent connect/close operations.
- Treat this as a driver bug and file a report with a reproducible trace.
When it happens
Trigger: ReleaseConnection() called (via ConnectAsync's cleanup path) more times than ConnectAsync succeeded incrementing _activeConnections — e.g. double-release on a failure path or releasing after disposal raced the connect.
Common situations: Races between connection close/dispose and concurrent connect attempts; calling internal release APIs from custom wrapper code around TursoSyncDatabase.
Related errors
- Turso sync operations cannot be reentered from the sync HTTP
- The transaction has completed.
- {method} requires an open data reader.
- The connection is already open.
- Turso database is closed.
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-31).
Data as JSON: /api/errors/1c9b6a6d119edea3.
Report an issue: GitHub.