tursodatabase/turso · error · NotSupportedException

SQLite facade batches are available only for direct remote o

Error message

SQLite facade batches are available only for direct remote or embedded replica connections.

What it means

This NotSupportedException is thrown by CreateDbBatch (the ADO.NET DbProviderFactory hook behind CreateBatch) when the SqliteConnection is not backed by the managed Turso connection. Batching through the SQLite facade relies on managed statement execution, which only direct remote and embedded replica connections provide.

Source

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

        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()
    {
        if (_managedConnection is null)
        {
            throw new NotSupportedException(
                "SQLite facade batches are available only for direct remote or embedded replica connections.");
        }

        return new SqliteBatch(this);
    }

    protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
        => BeginTransaction(isolationLevel);

    protected override ValueTask<DbTransaction> BeginDbTransactionAsync(
        IsolationLevel isolationLevel,
        CancellationToken cancellationToken)
    {
        cancellationToken.ThrowIfCancellationRequested();
        return ValueTask.FromResult<DbTransaction>(BeginTransaction(isolationLevel));
    }

    protected override void Dispose(bool disposing)

View on GitHub (pinned to 6c72522679)

Solutions

  1. Use a managed Turso connection (direct remote or embedded replica) when you need DbBatch support
  2. For local connections, execute statements as individual DbCommands instead of a DbBatch
  3. Guard with conn.IsManagedConnection before calling CreateBatch and fall back to per-statement commands

Example fix

// before
using var batch = localConn.CreateBatch(); // throws

// after
if (localConn.IsManagedConnection)
{
    using var batch = localConn.CreateBatch();
}
else
{
    foreach (var sql in statements) { /* execute individual commands */ }
}
Defensive patterns

Strategy: fallback

Validate before calling

if (!conn.IsManagedConnection) return ExecuteSequentially(conn, statements);

Type guard

DbBatch? TryCreateBatch(SqliteConnection c) => c.IsManagedConnection ? c.CreateBatch() : null;

Try / catch

try { return conn.CreateBatch(); }
catch (NotSupportedException ex) when (ex.Message.Contains("facade batches"))
{
    return null; // fall back to commands
}

Prevention

When it happens

Trigger: Calling conn.CreateBatch() (or letting DbBatch-based code paths invoke CreateDbBatch) on a SqliteConnection created from a plain local connection string (_managedConnection is null).

Common situations: Generic ADO.NET code that uses DbBatch everywhere now that .NET exposes it, run against local SQLite connections; factory-based data access layers unaware the backend differs per connection type.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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