tursodatabase/turso · error · InvalidOperationException
Managed transactions cannot be completed through raw transac
Error message
Managed transactions cannot be completed through raw transaction-control SQL.
What it means
MarkCompletedExternally is invoked when the database reports the transaction ended via raw SQL (e.g. COMMIT or ROLLBACK executed as a statement). For managed transactions, whose lifecycle is owned by the driver's replication/sync machinery, completing them through raw SQL is unsupported, so the library throws InvalidOperationException.
Source
Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteTransaction.cs:255
}
finally
{
Complete();
}
}
else if (disposing && !_completed && _connection is { State: ConnectionState.Open })
Rollback();
else if (disposing && _connection is not null && ReferenceEquals(_connection.Transaction, this))
_connection.Transaction = null;
base.Dispose(disposing);
}
internal void MarkCompletedExternally(bool rolledBack)
{
if (_managedTransaction is not null)
{
throw new InvalidOperationException(
"Managed transactions cannot be completed through raw transaction-control SQL.");
}
if (rolledBack)
{
_externalRollback = true;
return;
}
Complete();
}
private void Complete()
{
var connection = _connection;
if (connection is null)
{
_completed = true;View on GitHub (pinned to 6c72522679)
Solutions
- Use SqliteTransaction.BeginTransaction/Commit/Rollback instead of raw transaction-control SQL on managed connections.
- Remove COMMIT/ROLLBACK statements from ad-hoc SQL scripts executed on managed-transaction connections.
- Catch InvalidOperationException and re-run the work using the transaction API if raw SQL cannot be avoided.
Example fix
// before
await conn.ExecuteNonQueryAsync("COMMIT;");
// after
await managedTx.CommitAsync(); Defensive patterns
Strategy: validation
Validate before calling
if (usingManagedTransaction)
throw new NotSupportedException("Do not run raw BEGIN/COMMIT/ROLLBACK SQL on managed transactions."); Try / catch
try { await conn.ExecuteNonQueryAsync(sql); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Managed transactions"))
{ /* reroute to managedTx.CommitAsync/RollbackAsync */ } Prevention
- Strip transaction-control statements from SQL scripts before executing on managed connections.
- Use BeginTransaction/CommitAsync/RollbackAsync exclusively for transaction boundaries.
- Audit any code that concatenates SQL containing 'COMMIT' or 'ROLLBACK'.
When it happens
Trigger: Executing transaction-control SQL (BEGIN/COMMIT/ROLLBACK) directly through a TursoCommand/ExecuteNonQuery while a managed transaction (created via the managed-transaction API, e.g. on a replica/sync-enabled connection) is active.
Common situations: Porting ADO.NET code that issues 'BEGIN; ...; COMMIT;' strings manually; stored scripts containing transaction control run against a sync-enabled connection with an active managed transaction.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Transaction must be a SqliteTransaction.
- Embedded replica sync is not supported yet by the .NET provi
- Embedded replica connections are not supported yet by the .N
- Sync Interval requires embedded replica support, which is no
- Auth Token requires a remote Turso URL Data Source.
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-09-06).
Data as JSON: /api/errors/8a9ee343d0097638.
Report an issue: GitHub.