{"record":{"id":"8a9ee343d0097638","repo":"tursodatabase/turso","slug":"managed-transactions-cannot-be-completed-through-r","errorCode":null,"errorMessage":"Managed transactions cannot be completed through raw transaction-control SQL.","messagePattern":"Managed transactions cannot be completed through raw transaction-control SQL\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data.Sqlite/SqliteTransaction.cs","lineNumber":255,"sourceCode":"            }\n            finally\n            {\n                Complete();\n            }\n        }\n        else if (disposing && !_completed && _connection is { State: ConnectionState.Open })\n            Rollback();\n        else if (disposing && _connection is not null && ReferenceEquals(_connection.Transaction, this))\n            _connection.Transaction = null;\n\n        base.Dispose(disposing);\n    }\n\n    internal void MarkCompletedExternally(bool rolledBack)\n    {\n        if (_managedTransaction is not null)\n        {\n            throw new InvalidOperationException(\n                \"Managed transactions cannot be completed through raw transaction-control SQL.\");\n        }\n\n        if (rolledBack)\n        {\n            _externalRollback = true;\n            return;\n        }\n\n        Complete();\n    }\n\n    private void Complete()\n    {\n        var connection = _connection;\n        if (connection is null)\n        {\n            _completed = true;","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data.Sqlite/SqliteTransaction.cs#L237-L273","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait conn.ExecuteNonQueryAsync(\"COMMIT;\");\n// after\nawait managedTx.CommitAsync();","handlingStrategy":"validation","validationCode":"if (usingManagedTransaction)\n    throw new NotSupportedException(\"Do not run raw BEGIN/COMMIT/ROLLBACK SQL on managed transactions.\");","typeGuard":null,"tryCatchPattern":"try { await conn.ExecuteNonQueryAsync(sql); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Managed transactions\"))\n{ /* reroute to managedTx.CommitAsync/RollbackAsync */ }","preventionTips":["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'."],"tags":["csharp","dotnet","transaction","raw-sql"],"backgroundTag":"unsupported-operation","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-09-06T07:15:26.990Z","contentChangedAt":"2026-09-06T07:15:26.990Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}