tursodatabase/turso · error · InvalidOperationException

ExecuteBatch requires an open connection.

Error message

ExecuteBatch requires an open connection.

What it means

ValidateBatch enforces that the batch's connection is open before executing; a closed or broken connection throws InvalidOperationException with the 'ExecuteBatch requires an open connection' message (via CallRequiresOpenConnection resource), mirroring standard ADO.NET behavior.

Source

Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteBatch.cs:373

        catch
        {
            managedBatch.Dispose();
            throw;
        }
    }

    private SqliteConnection ValidateBatch()
    {
        var connection = _connection
                         ?? throw new InvalidOperationException(
                             "Connection must be set before executing a batch.");
        if (!connection.IsManagedConnection)
        {
            throw new NotSupportedException(
                "SQLite facade batches are available only for direct remote or embedded replica connections.");
        }
        if (connection.State != ConnectionState.Open)
            throw new InvalidOperationException(Properties.Resources.CallRequiresOpenConnection("ExecuteBatch"));
        if (_transaction is { IsCompleted: true })
            throw new InvalidOperationException(Properties.Resources.TransactionCompleted);
        if (_transaction is not null && !ReferenceEquals(_transaction.Connection, connection))
            throw new InvalidOperationException(Properties.Resources.TransactionConnectionMismatch);
        if (connection.Transaction is not null
            && !ReferenceEquals(_transaction, connection.Transaction))
        {
            throw new InvalidOperationException(Properties.Resources.TransactionRequired);
        }
        if (_batchCommands.Count == 0)
            throw new InvalidOperationException("Batch must contain at least one command.");

        return connection;
    }

    private int SetRecordsAffected(BatchState state)
    {
        var total = 0;

View on GitHub (pinned to 6c72522679)

Solutions

  1. Call await connection.OpenAsync() (or Open()) before executing the batch
  2. Check connection.State == ConnectionState.Open before executing and open if needed
  3. Don't dispose the connection (using scope) before the batch completes; for drops, recreate/reopen the connection

Example fix

// before
var conn = new SqliteConnection(cs);
await batch.ExecuteReaderAsync(); // InvalidOperationException
// after
var conn = new SqliteConnection(cs);
await conn.OpenAsync();
await batch.ExecuteReaderAsync();
Defensive patterns

Strategy: validation

Validate before calling

if (connection.State != ConnectionState.Open)
    await connection.OpenAsync();

Type guard

static bool IsOpen(System.Data.ConnectionState s) => s == ConnectionState.Open;

Try / catch

try { await batch.ExecuteReaderAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("open connection") || ex.Message.Contains("open")) { /* reopen connection and retry once */ }

Prevention

When it happens

Trigger: Calling ExecuteReader/ExecuteBatch before calling connection.Open(), after connection.Close()/Dispose(), or after the connection dropped (broken state).

Common situations: Async code that opens the connection in another method but awaits it incorrectly; connection disposed by a using block before the batch runs; network drop putting a remote connection into a non-Open state.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-09-06). Data as JSON: /api/errors/6d3f099dd3b9d137. Report an issue: GitHub.