{"record":{"id":"3d830c3b8d909809","repo":"tursodatabase/turso","slug":"5-3d830c","errorCode":"5","errorMessage":"SQLite Error {errorCode}: '{message}'.","messagePattern":"SQLite Error (.+?): '(.+?)'\\.","errorType":"exception","errorClass":"SqliteException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data.Sqlite/SqliteConnection.cs","lineNumber":486,"sourceCode":"        {\n            _pendingExtensions.Add((file, proc));\n            return;\n        }\n\n        LoadExtensionCore(file, proc);\n    }\n\n    public virtual void BackupDatabase(SqliteConnection destination)\n        => BackupDatabase(destination, \"main\", \"main\");\n\n    public virtual void BackupDatabase(SqliteConnection destination, string destinationName, string sourceName)\n    {\n        ThrowIfManagedLocalOnly(nameof(BackupDatabase));\n        if (_database is null)\n            throw new InvalidOperationException(Properties.Resources.CallRequiresOpenConnection(\"BackupDatabase\"));\n        ArgumentNullException.ThrowIfNull(destination);\n        if (Transaction is not null)\n            throw new SqliteException(Properties.Resources.SqliteNativeError(5, \"database is locked\"), 5);\n        if (destination.State != ConnectionState.Open)\n            destination.Open();\n\n        foreach (var createSql in GetSchemaSql())\n            destination.ExecuteNonQuery(createSql);\n\n        foreach (var tableName in GetUserTableNames())\n            CopyTableRows(destination, tableName);\n    }\n\n    public new virtual SqliteCommand CreateCommand() => new(this) { Transaction = Transaction };\n\n    protected override DbCommand CreateDbCommand() => CreateCommand();\n\n    protected override DbBatch CreateDbBatch()\n    {\n        if (_managedConnection is null)\n        {","sourceCodeStart":468,"sourceCodeEnd":504,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data.Sqlite/SqliteConnection.cs#L468-L504","documentation":"BackupDatabase deliberately throws SqliteException with native error code 5 (SQLITE_BUSY, 'database is locked') when the source connection has an active transaction. A physical copy cannot be taken while the connection's own transaction holds locks on the database; rather than attempting a backup that would contend, the provider translates this precondition into the standard busy error. This is raised before any schema or row copying starts.","triggerScenarios":"'using var tx = conn.BeginTransaction(); ... conn.BackupDatabase(dst);' on the same connection; calling BackupDatabase from code that runs inside a unit-of-work scope holding a transaction; committing asynchronously and backing up before the commit lands.","commonSituations":"Backup jobs triggered while writes are in flight, repository-level backup helpers invoked inside transactional service methods, and test teardown that snapshots the database without unwinding the test transaction.","solutions":["Commit or roll back (and dispose) the source transaction before calling BackupDatabase.","Restructure so backups run outside transaction scopes (e.g. a dedicated connection/path with no active Transaction).","If you need a consistent copy mid-workflow, commit first, then back up, then continue in a new transaction."],"exampleFix":"// before\nusing var conn = new SqliteConnection(cs);\nconn.Open();\nusing var tx = conn.BeginTransaction();\nInsertRows(conn);\nconn.BackupDatabase(dst); // throws SqliteException code 5: database is locked\n\n// after\nusing var conn = new SqliteConnection(cs);\nconn.Open();\nusing (var tx = conn.BeginTransaction())\n{\n    InsertRows(conn);\n    tx.Commit();\n}\nconn.BackupDatabase(dst); // no active transaction -> succeeds","handlingStrategy":"validation","validationCode":"static void BackupOutsideTransactions(SqliteConnection src, string dstCs)\n{\n    if (src.Transaction is not null)\n        throw new InvalidOperationException($\"Commit or roll back the active transaction before backup.\");\n    if (src.State != ConnectionState.Open) src.Open();\n    using var dst = new SqliteConnection(dstCs);\n    dst.Open();\n    src.BackupDatabase(dst);\n}","typeGuard":"static bool HasActiveTransaction(SqliteConnection conn) => conn.Transaction is not null;","tryCatchPattern":"try\n{\n    src.BackupDatabase(dst);\n}\ncatch (SqliteException ex) when (ex.SqliteErrorCode == 5)\n{\n    // SQLITE_BUSY from an active source transaction (or external locker):\n    // settle transactions, then retry the backup once.\n    throw new InvalidOperationException(\"Backup blocked by an active transaction; commit/rollback and retry.\", ex);\n}","preventionTips":["Never call BackupDatabase from inside a transactional scope on the source connection.","Schedule backups from a path that provably holds no open SqliteTransaction.","Treat error code 5 during backup as a lifecycle bug to fix, not a transient condition to blindly retry."],"tags":["ado-net","sqlite","turso","backup","transactions","locking","sqlite-busy"],"backgroundTag":"database-locked","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}