tursodatabase/turso · error · InvalidOperationException
Embedded replica '{path}' is already open exclusively.
Error message
Embedded replica '{path}' is already open exclusively. What it means
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.
Source
Thrown at bindings/dotnet/src/Turso.Data/TursoReplicaRegistry.cs:41
var database = await TursoSyncDatabase
.CreateAsync(options, cancellationToken)
.ConfigureAwait(false);
return Lease.CreateStandalone(
database,
new TursoAutomaticSyncCoordinator(database, syncInterval, timeProvider));
}
var path = Path.GetFullPath(options.Path);
var fingerprint = Fingerprint.Create(options, syncInterval);
Entry entry;
lock (Gate)
{
if (Entries.TryGetValue(path, out entry!))
{
if (entry.Closing)
throw new InvalidOperationException($"Embedded replica '{path}' is closing.");
if (!pooling || !entry.Pooling)
throw new InvalidOperationException($"Embedded replica '{path}' is already open exclusively.");
if (entry.Fingerprint != fingerprint)
throw new InvalidOperationException($"Embedded replica '{path}' is already open with different options.");
checked
{
entry.ReferenceCount++;
}
}
else
{
entry = new Entry(path, pooling, fingerprint)
{
ReferenceCount = 1,
};
entry.Initialization = InitializeAsync(entry, options, syncInterval, timeProvider);
Entries.Add(path, entry);
}
}View on GitHub (pinned to 6c72522679)
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.
Example fix
// before var a = new TursoConnection(replicaPath); await a.OpenAsync(); // exclusive var b = new TursoConnection(replicaPath); await b.OpenAsync(); // throws // after var a = new TursoConnection(pooledReplicaConnString); await a.OpenAsync(); var b = new TursoConnection(pooledReplicaConnString); await b.OpenAsync(); // shares registry entry
Defensive patterns
Strategy: try-catch
Validate before calling
// Track openings in app code:
if (openReplicaPaths.Contains(path) && !requestIsPooling)
throw new InvalidOperationException($"Replica '{path}' is already open; enable pooling to share it."); Try / catch
try { conn = await registry.AcquireAsync(path, pooling, fingerprint); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already open exclusively"))
{ conn = reuseExistingConnection(path); } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Embedded replica '{path}' is closing.
- Embedded replica sync is not supported yet by the .NET provi
- Embedded replica connections are not supported yet by the .N
- Sync Interval requires embedded replica support, which is no
- Auth Token requires a remote Turso URL Data Source.
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-09-06).
Data as JSON: /api/errors/e81cdb456ea45ea8.
Report an issue: GitHub.