{"record":{"id":"4e960259faaeb560","repo":"tursodatabase/turso","slug":"sqlitecommand-tosqliteexception-ex","errorCode":null,"errorMessage":"SqliteCommand.ToSqliteException(ex)","messagePattern":"SqliteCommand\\.ToSqliteException\\(ex\\)","errorType":"exception","errorClass":"SqliteException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data.Sqlite/SqliteTransaction.cs","lineNumber":33,"sourceCode":"    {\n        _connection = connection;\n        _isolationLevel = NormalizeIsolationLevel(connection, isolationLevel, deferred);\n\n        if (_isolationLevel == IsolationLevel.ReadUncommitted)\n            connection.ReadUncommitted = true;\n\n        if (connection.IsManagedConnection)\n        {\n            try\n            {\n                _managedTransaction = new global::Turso.TursoTransaction(\n                    connection.ManagedConnection,\n                    _isolationLevel,\n                    deferred);\n            }\n            catch (Turso.Raw.Public.TursoException ex)\n            {\n                throw SqliteCommand.ToSqliteException(ex);\n            }\n\n            return;\n        }\n\n        Execute(_isolationLevel == IsolationLevel.Serializable && !deferred ? \"BEGIN IMMEDIATE;\" : \"BEGIN;\");\n    }\n\n    public override IsolationLevel IsolationLevel => _isolationLevel;\n\n    public override bool SupportsSavepoints => true;\n\n    protected override DbConnection? DbConnection => Connection;\n\n    public new virtual SqliteConnection? Connection => _connection;\n\n    internal bool IsCompleted => _completed;\n","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data.Sqlite/SqliteTransaction.cs#L15-L51","documentation":"The SqliteTransaction constructor asks the managed connection to BEGIN a transaction (BEGIN IMMEDIATE for serializable non-deferred transactions, otherwise BEGIN). If the backend rejects the BEGIN (e.g. a transaction is already active or the connection failed), the TursoException is converted to a SqliteException. The deferred fallback path uses plain text 'BEGIN;' via Execute.","triggerScenarios":"calling conn.BeginTransaction() while another transaction is already open on the same connection; connection to remote Turso server is broken; backend rejects BEGIN IMMEDIATE because the database is locked.","commonSituations":"Nested transaction attempts (BeginTransaction inside a using-block whose transaction wasn't committed/disposed), parallel use of one connection from multiple threads, busy database under contention.","solutions":["Ensure the previous SqliteTransaction is committed, rolled back, or disposed before starting a new one on the same connection.","Use one transaction at a time per connection; don't share a SqliteConnection across threads without synchronization.","Catch SqliteException and check for SQLITE_BUSY (5) to implement retry/backoff on locked databases.","If available, enable connection pooling per logical operation instead of manual nested transactions."],"exampleFix":"// before\nvar tx = conn.BeginTransaction();\nvar tx2 = conn.BeginTransaction(); // throws: transaction already active\n// after\nusing (var tx = conn.BeginTransaction())\n{\n    // ...\n    tx.Commit();\n} // dispose ends the transaction before another can begin","handlingStrategy":"try-catch","validationCode":"// ensure no transaction is active before beginning a new one\nif (conn.EnlistedTransaction != null || _currentTx != null)\n    throw new InvalidOperationException(\"transaction already active on this connection\");","typeGuard":"static bool CanBeginTransaction(SqliteConnection conn) => conn.State == ConnectionState.Open;","tryCatchPattern":"try\n{\n    using var tx = conn.BeginTransaction(IsolationLevel.ReadCommitted);\n    // ... work, tx.Commit()\n}\ncatch (SqliteException ex) when (ex.SqliteErrorCode == 5)\n{\n    // SQLITE_BUSY: retry with backoff\n}\ncatch (SqliteException ex)\n{\n    logger.LogError(ex, \"BEGIN failed\");\n    throw;\n}","preventionTips":["Never nest BeginTransaction on one connection","Always use 'using' so transactions end deterministically","Don't share a SqliteConnection across concurrent tasks","Retry BEGIN IMMEDIATE with backoff when the database is busy"],"tags":["dotnet","sqlite","transaction","ado-net"],"backgroundTag":"sql-query-failed","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-09-06T07:15:26.990Z","contentChangedAt":"2026-09-06T07:15:26.990Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}