{"record":{"id":"f73d23568cd780fc","repo":"litedb-org/LiteDB","slug":"0-f73d23","errorCode":"0","errorMessage":"This transaction are invalid state","messagePattern":"This transaction are invalid state","errorType":"exception","errorClass":"LiteException","httpStatus":null,"severity":"error","filePath":"LiteDB/Engine/Services/TransactionService.cs","lineNumber":124,"sourceCode":"            }\n            else\n            {\n                // if not exits, let's create here\n                _snapshots[collection] = snapshot = create();\n            }\n\n            // update transaction mode to write in first write snaphost request\n            if (mode == LockMode.Write) _mode = LockMode.Write;\n\n            return snapshot;\n        }\n\n        /// <summary>\n        /// If current transaction contains too much pages, now is safe to remove clean pages from memory and flush to wal disk dirty pages\n        /// </summary>\n        public void Safepoint()\n        {\n            if (_state != TransactionState.Active) throw new LiteException(0, \"This transaction are invalid state\");\n\n            if (_monitor.CheckSafepoint(this))\n            {\n                LOG($\"safepoint flushing transaction pages: {_transPages.TransactionSize}\", \"TRANSACTION\");\n\n                // if any snapshot are writable, persist pages\n                if (_mode == LockMode.Write)\n                {\n                    this.PersistDirtyPages(false);\n                }\n\n                // clear local pages in all snapshots (read/write snapshosts)\n                foreach (var snapshot in _snapshots.Values)\n                {\n                    snapshot.Clear();\n                }\n\n                // there is no local pages in cache and all dirty pages are in log file","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/litedb-org/LiteDB/blob/f906a5f850678719e39a39a006cb66dcae563cfa/LiteDB/Engine/Services/TransactionService.cs#L106-L142","documentation":"Thrown by TransactionService.Safepoint when the transaction's _state is not TransactionState.Active (i.e. already Committed or Aborted). Safepoint runs periodically to flush dirty pages when a transaction holds too many pages; calling any operation that triggers it after the transaction ended hits this guard.","triggerScenarios":"Continuing to use a transaction (or a cursor/snapshot derived from it) after Commit() or after it was auto-aborted; a deferred/lazy query (IEnumerable yield) that materializes after the transaction was disposed.","commonSituations":"Returning an IQueryable/IEnumerable from a using-block that disposed the transaction; lazy query enumeration outside the transaction scope; double-commit; long-running LINQ over documents whose safepoint fires after the tx was aborted by an earlier error.","solutions":["Materialize query results (ToList()/ToArray()) before the transaction is committed or disposed.","Keep all read/write work inside the transaction's using-scope.","Avoid reusing a transaction object after Commit; start a new one if more work is needed.","Catch and handle earlier exceptions so a transaction is not silently left half-aborted while later code keeps using it."],"exampleFix":"// before\nList<BsonDocument> docs;\nusing (var tx = db.BeginTransaction()) {\n    docs = tx.GetCollection(\"c\").FindAll(); // lazy\n    tx.Commit();\n}\nforeach (var d in docs) { } // materializes after tx ended -> throws\n\n// after\nusing (var tx = db.BeginTransaction()) {\n    var docs = tx.GetCollection(\"c\").FindAll().ToList();\n    tx.Commit();\n    Process(docs);\n}","handlingStrategy":"validation","validationCode":"// materialize inside the transaction scope\nusing (var tx = db.BeginTransaction()) {\n    var rows = tx.GetCollection(\"c\").FindAll().ToList(); // eager\n    tx.Commit();\n    return rows; // safe to use after commit\n}","typeGuard":null,"tryCatchPattern":"try { /* operation that may trigger Safepoint */ }\ncatch (LiteException ex) when (ex.Message.Contains(\"invalid state\")) {\n    // transaction already finished: start a fresh one and redo\n}","preventionTips":["Never enumerate a query lazily after its transaction ends.","Scope all work inside the transaction using-block.","Do not reuse a transaction object after Commit."],"tags":["transactions","state","lazy-enumeration"],"backgroundTag":null,"analyzedSha":"f906a5f850678719e39a39a006cb66dcae563cfa","analyzedAt":"2026-08-13T21:56:30.148Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}