{"record":{"id":"32d6996b6fea7438","repo":"tursodatabase/turso","slug":"embedded-replica-lease-ownership-is-unbalanced","errorCode":null,"errorMessage":"Embedded replica lease ownership is unbalanced.","messagePattern":"Embedded replica lease ownership is unbalanced\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoReplicaRegistry.cs","lineNumber":108,"sourceCode":"        }\n        catch\n        {\n            lock (Gate)\n            {\n                if (Entries.TryGetValue(entry.Path, out var current) && ReferenceEquals(current, entry))\n                    Entries.Remove(entry.Path);\n            }\n            throw;\n        }\n    }\n\n    private static Exception? ReleaseReference(Entry entry)\n    {\n        Holder? holder;\n        lock (Gate)\n        {\n            if (entry.ReferenceCount <= 0)\n                throw new InvalidOperationException(\"Embedded replica lease ownership is unbalanced.\");\n            entry.ReferenceCount--;\n            if (entry.ReferenceCount != 0)\n            {\n                var status = entry.Holder?.Coordinator.Status;\n                return status?.State == TursoAutomaticSyncState.Faulted\n                    ? status.LastException\n                    : null;\n            }\n\n            entry.Closing = true;\n            entry.InitializationCancellation.Cancel();\n            holder = entry.Holder;\n            if (holder is null)\n            {\n                _ = DisposeAfterInitializationAsync(entry);\n                return null;\n            }\n        }","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data/TursoReplicaRegistry.cs#L90-L126","documentation":"ReleaseReference decrements the reference count of a pooled embedded replica entry when a connection is disposed. The registry expects every Release to be paired with exactly one Acquire; if the count is already <= 0 the lease bookkeeping is corrupt, so it throws this InvalidOperationException to surface the internal bug.","triggerScenarios":"Disposing/closing a TursoConnection that acquired an embedded replica lease more than once, releasing a reference after the entry was already fully released, or double-dispose racing with another dispose while ReferenceCount is already zero.","commonSituations":"Double disposal of the same connection (e.g. using-block plus explicit Dispose or finalizer path), copying a connection object and disposing both copies, a bug in custom pooling code that calls release APIs directly.","solutions":["Ensure each connection is disposed exactly once (don't call both Close and Dispose, don't dispose inside and outside a using block).","Check for code that shares one TursoConnection across threads and disposes it concurrently.","If it appears without obvious double-dispose, report it as a bug in Turso.Data reference counting.","Guard disposal with an idempotent wrapper around your connection lifetime management."],"exampleFix":"// before\ntursoConn.Dispose();\n// ... later, accidental second release\ntursoConn.Dispose();\n\n// after: single idempotent disposal\nif (!tursoDisposed) { tursoConn.Dispose(); tursoDisposed = true; }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { tursoConn.Dispose(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"lease ownership is unbalanced\"))\n{\n    // bookkeeping bug or double dispose; log and stop touching this connection\n}","preventionTips":["Dispose each connection exactly once; rely on using blocks rather than manual Close+Dispose.","Never share a TursoConnection across threads without synchronization.","Treat connection objects as single-owner; don't copy references and dispose twice."],"tags":["dotnet","embedded-replica","refcount","lifecycle"],"backgroundTag":"internal-invariant-violation","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"}