{"record":{"id":"e81cdb456ea45ea8","repo":"tursodatabase/turso","slug":"embedded-replica-path-is-already-open-exclusiv","errorCode":null,"errorMessage":"Embedded replica '{path}' is already open exclusively.","messagePattern":"Embedded replica '(.+?)' is already open exclusively\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoReplicaRegistry.cs","lineNumber":41,"sourceCode":"            var database = await TursoSyncDatabase\n                .CreateAsync(options, cancellationToken)\n                .ConfigureAwait(false);\n            return Lease.CreateStandalone(\n                database,\n                new TursoAutomaticSyncCoordinator(database, syncInterval, timeProvider));\n        }\n\n        var path = Path.GetFullPath(options.Path);\n        var fingerprint = Fingerprint.Create(options, syncInterval);\n        Entry entry;\n        lock (Gate)\n        {\n            if (Entries.TryGetValue(path, out entry!))\n            {\n                if (entry.Closing)\n                    throw new InvalidOperationException($\"Embedded replica '{path}' is closing.\");\n                if (!pooling || !entry.Pooling)\n                    throw new InvalidOperationException($\"Embedded replica '{path}' is already open exclusively.\");\n                if (entry.Fingerprint != fingerprint)\n                    throw new InvalidOperationException($\"Embedded replica '{path}' is already open with different options.\");\n\n                checked\n                {\n                    entry.ReferenceCount++;\n                }\n            }\n            else\n            {\n                entry = new Entry(path, pooling, fingerprint)\n                {\n                    ReferenceCount = 1,\n                };\n                entry.Initialization = InitializeAsync(entry, options, syncInterval, timeProvider);\n                Entries.Add(path, entry);\n            }\n        }","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data/TursoReplicaRegistry.cs#L23-L59","documentation":"AcquireAsync enforces sharing rules per replica path: if an existing entry is not flagged for pooling, or the new request is not pooling, the path is already held exclusively and a second acquisition throws InvalidOperationException. Only pooled, compatible openers may share a replica.","triggerScenarios":"Opening a second connection to the same embedded replica path when the first was opened non-pooling (exclusive), or opening an exclusive (non-pooling) connection while a pooled one already exists.","commonSituations":"Two parts of an app each creating their own connection to the same replica file with different pooling settings; a background sync service holding an exclusive replica while the app tries to open another connection; stale connection leaked in a long-running process.","solutions":["Open all connections to a given replica path with pooling enabled so they share the registry entry.","Ensure prior exclusive connections are disposed before opening the replica again.","Search the codebase for other TursoConnection instances using the same path and centralize replica access.","Catch InvalidOperationException and reuse an existing connection from your own DI/pool layer instead."],"exampleFix":"// before\nvar a = new TursoConnection(replicaPath); await a.OpenAsync(); // exclusive\nvar b = new TursoConnection(replicaPath); await b.OpenAsync(); // throws\n// after\nvar a = new TursoConnection(pooledReplicaConnString); await a.OpenAsync();\nvar b = new TursoConnection(pooledReplicaConnString); await b.OpenAsync(); // shares registry entry","handlingStrategy":"try-catch","validationCode":"// Track openings in app code:\nif (openReplicaPaths.Contains(path) && !requestIsPooling)\n    throw new InvalidOperationException($\"Replica '{path}' is already open; enable pooling to share it.\");","typeGuard":null,"tryCatchPattern":"try { conn = await registry.AcquireAsync(path, pooling, fingerprint); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already open exclusively\"))\n{ conn = reuseExistingConnection(path); }","preventionTips":["Always open embedded replicas in pooling mode unless exclusivity is required.","Dispose exclusive connections promptly after use.","Keep one DI-managed connection per replica path instead of ad-hoc instances."],"tags":["csharp","dotnet","replica","exclusive","pooling"],"backgroundTag":"invalid-state-transition","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-09-06T07:15:26.990Z","contentChangedAt":"2026-09-06T07:15:26.990Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}