tursodatabase/turso · error · InvalidOperationException
The connection is already open.
Error message
The connection is already open.
What it means
SqliteConnection.Open() throws InvalidOperationException when the connection already holds a native database handle (_database is not null). The provider does not treat a second Open as a no-op (unlike some ADO.NET providers); it demands one Open per connection instance. State derives directly from whether the native handle exists, so this fires on any duplicate Open.
Source
Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteConnection.cs:163
ObjectDisposedException.ThrowIf(_disposed, this);
if (_managedConnection is not null)
{
var managedOriginalState = State;
try
{
_managedConnection.Open();
RegisterManagedReplicaCallbacks();
}
finally
{
NotifyManagedStateChange(managedOriginalState);
}
return;
}
if (_database is not null)
throw new InvalidOperationException("The connection is already open.");
if (!string.IsNullOrEmpty(_connectionOptions.Password))
throw new InvalidOperationException(Properties.Resources.EncryptionNotSupported("e_sqlite3"));
var originalState = State;
var filename = NormalizeDataSource(_connectionOptions);
var readOnly = _connectionOptions.Mode == SqliteOpenMode.ReadOnly;
var sharedMemoryPath = IsSharedMemory(_connectionOptions) ? RegisterSharedMemoryFile(filename) : null;
try
{
_database = TursoBindings.OpenDatabase(filename);
_dataSource = filename;
_readOnly = readOnly;
_sharedMemoryPath = sharedMemoryPath;
ApplyExtensionSettings();
ApplyConnectionOptions();
RegisterScalarFunctions();
RegisterAggregateFunctions();
RegisterCollations();View on GitHub (pinned to 6c72522679)
Solutions
- Guard opens: 'if (conn.State != ConnectionState.Open) conn.Open();'.
- Restrict opening to one owner of the connection (e.g. the factory or the outermost scope), not every consumer.
- For concurrent access, create one SqliteConnection per task/operation instead of sharing and double-opening one instance.
Example fix
// before var conn = new SqliteConnection(cs); conn.Open(); DoWork(conn); DoMoreWork(conn); // internally calls conn.Open() -> throws // after var conn = new SqliteConnection(cs); if (conn.State != ConnectionState.Open) conn.Open(); DoWork(conn); DoMoreWork(conn); // guarded open is a no-op
Defensive patterns
Strategy: validation
Validate before calling
static void EnsureOpen(SqliteConnection conn)
{
if (conn.State != ConnectionState.Open)
conn.Open();
} Prevention
- Open the connection exactly once at the boundary that owns its lifetime.
- Give concurrent operations their own connection instances.
- Audit shared helpers for unconditional Open() calls.
When it happens
Trigger: Calling conn.Open() twice without an intervening Close/Dispose; 'ensure open' helpers that unconditionally call Open; multiple components sharing one SqliteConnection and each opening it; retry wrappers that re-open after a transient failure without checking state.
Common situations: Shared connections in DI services where several code paths open independently, generic ADO.NET infrastructure ported from SqlClient (where Open is often idempotent in practice via pooling), and race conditions where two tasks open the same instance concurrently.
Related errors
- {method} requires an open connection.
- The connection string can only be set when the connection is
- Changing databases is not supported.
- The connection is not open.
- Encryption is not supported by {libraryName}.
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-09-06).
Data as JSON: /api/errors/8b37039f729515b2.
Report an issue: GitHub.