tursodatabase/turso · error · InvalidOperationException

BackupDatabase requires an open connection.

Error message

BackupDatabase requires an open connection.

What it means

This InvalidOperationException is thrown by BackupDatabase when the source SqliteConnection is not open (_database is null). Native backup requires an open connection to read pages from the source database. A preceding ThrowIfManagedLocalOnly also rejects managed-local connections.

Source

Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteConnection.cs:483

            throw new NotSupportedException("Custom extension entry points are not yet supported by the Turso SQLite-compatible provider.");

        if (_database is null)
        {
            _pendingExtensions.Add((file, proc));
            return;
        }

        LoadExtensionCore(file, proc);
    }

    public virtual void BackupDatabase(SqliteConnection destination)
        => BackupDatabase(destination, "main", "main");

    public virtual void BackupDatabase(SqliteConnection destination, string destinationName, string sourceName)
    {
        ThrowIfManagedLocalOnly(nameof(BackupDatabase));
        if (_database is null)
            throw new InvalidOperationException(Properties.Resources.CallRequiresOpenConnection("BackupDatabase"));
        ArgumentNullException.ThrowIfNull(destination);
        if (Transaction is not null)
            throw new SqliteException(Properties.Resources.SqliteNativeError(5, "database is locked"), 5);
        if (destination.State != ConnectionState.Open)
            destination.Open();

        foreach (var createSql in GetSchemaSql())
            destination.ExecuteNonQuery(createSql);

        foreach (var tableName in GetUserTableNames())
            CopyTableRows(destination, tableName);
    }

    public new virtual SqliteCommand CreateCommand() => new(this) { Transaction = Transaction };

    protected override DbCommand CreateDbCommand() => CreateCommand();

    protected override DbBatch CreateDbBatch()

View on GitHub (pinned to 6c72522679)

Solutions

  1. Call conn.Open() before invoking BackupDatabase
  2. Verify conn.State == ConnectionState.Open prior to backup
  3. Ensure the connection object is not disposed before the backup completes

Example fix

// before
using var conn = new SqliteConnection(cs);
conn.BackupDatabase(dest); // throws: not open

// after
using var conn = new SqliteConnection(cs);
conn.Open();
conn.BackupDatabase(dest);
Defensive patterns

Strategy: validation

Validate before calling

if (source.State != ConnectionState.Open) source.Open();

Type guard

bool SourceReady(SqliteConnection c) => c.State == ConnectionState.Open;

Try / catch

try { source.BackupDatabase(dest); }
catch (InvalidOperationException ex) when (ex.Message.Contains("open connection"))
{
    source.Open(); source.BackupDatabase(dest);
}

Prevention

When it happens

Trigger: Calling conn.BackupDatabase(destination) (or the destinationName/sourceName overload) while conn.State is Closed, e.g. before calling Open() or after Close()/Dispose().

Common situations: Copy-pasted backup code that opens only the destination connection (since BackupDatabase auto-opens the destination but never the source); disposing the source earlier in a using block than the backup call.

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


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