{"record":{"id":"1996c0d5f3632cb0","repo":"litedb-org/LiteDB","slug":"failed-to-begin-primary-transaction-for-reproducti","errorCode":null,"errorMessage":"Failed to begin primary transaction for reproduction.","messagePattern":"Failed to begin primary transaction for reproduction\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"LiteDB.ReproRunner/Repros/Issue_2586_RollbackTransaction/Program.cs","lineNumber":180,"sourceCode":"            try\n            {\n                db.Rollback();\n            }\n            catch (LiteException ex)\n            {\n                Log(host, $\"[{threadId}] Holder rollback threw: {ex.Message}\", ReproHostLogLevel.Warning);\n            }\n        }\n    }\n\n    private static bool RunFailingTransaction(ReproHostClient host, LiteDatabase db, ILiteCollection<LargeDocument> collection)\n    {\n        Console.WriteLine();\n        Log(host, $\"Starting write transaction on thread {Thread.CurrentThread.ManagedThreadId}.\");\n\n        if (!db.BeginTrans())\n        {\n            throw new InvalidOperationException(\"Failed to begin primary transaction for reproduction.\");\n        }\n\n        TransactionInspector? inspector = null;\n        var maxSize = 0;\n        var safepointTriggered = false;\n        var shouldTriggerSafepoint = false;\n\n        var payloadA = new string('A', 4_096);\n        var payloadB = new string('B', 4_096);\n        var payloadC = new string('C', 2_048);\n        var largeBinary = new byte[128 * 1024];\n\n        try\n        {\n            for (var i = 0; i < DocumentWriteCount; i++)\n            {\n                if (shouldTriggerSafepoint && !safepointTriggered)\n                {","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/litedb-org/LiteDB/blob/f906a5f850678719e39a39a006cb66dcae563cfa/LiteDB.ReproRunner/Repros/Issue_2586_RollbackTransaction/Program.cs#L162-L198","documentation":"Thrown by the Issue 2586 repro harness when db.BeginTrans() returned false on the primary thread. LiteDB's BeginTrans returns false (rather than throwing) when the calling thread already has an active transaction, so the repro treats that as a fatal setup failure because it needs a fresh primary transaction to drive the rollback path.","triggerScenarios":"Calling db.BeginTrans() on a thread that already began a transaction earlier and never committed/rolled it back; or reusing a LiteDatabase/LiteEngine whose ambient transaction was left open by a prior step of the repro. The 'primary transaction for reproduction' must be the first transaction on that thread.","commonSituations":"Repro/test code that begins a transaction in a setup phase and forgets to commit or roll back before the main phase; shared LiteDatabase instances across test methods without teardown; an earlier exception that skipped the Rollback call in a finally block.","solutions":["Ensure the primary thread has no open transaction: call db.Rollback() or db.Commit() (or dispose the LiteDatabase) before reaching RunFailingTransaction.","Use a fresh LiteDatabase instance for the primary write transaction so no ambient transaction is inherited.","Wrap the earlier transaction in try/finally so an exception always releases it.","Log whether BeginTrans returned false versus threw, to distinguish 'already in transaction' from a deeper engine error."],"exampleFix":"// before\nif (!db.BeginTrans())\n{\n    throw new InvalidOperationException(\"Failed to begin primary transaction for reproduction.\");\n}\n\n// after\n// release any ambient transaction left from setup\ntry { db.Rollback(); } catch { /* no active transaction */ }\nif (!db.BeginTrans())\n{\n    throw new InvalidOperationException(\"Failed to begin primary transaction for reproduction (thread already in a transaction?).\");\n}","handlingStrategy":"validation","validationCode":"// Ensure no ambient transaction before starting the primary one\ntry { db.Rollback(); }\ncatch (LiteException) { /* no active transaction; expected */ }\nif (!db.BeginTrans())\n{\n    throw new InvalidOperationException(\"Thread already in a transaction; cannot start primary reproduction transaction.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pair BeginTrans with a Commit/Rollback in try/finally so no transaction leaks across repro phases.","Use a fresh LiteDatabase instance per repro phase to avoid inheriting ambient state.","Treat BeginTrans returning false as 'already in transaction' and handle it explicitly."],"tags":["transaction","repro","begintrans","threading"],"backgroundTag":null,"analyzedSha":"f906a5f850678719e39a39a006cb66dcae563cfa","analyzedAt":"2026-08-13T21:56:30.148Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}