tursodatabase/turso · error · NotSupportedException

Multi-statement SqliteCommand execution requires Read Your W

Error message

Multi-statement SqliteCommand execution requires Read Your Writes=True or an explicit SqliteTransaction on a direct remote connection.

What it means

This NotSupportedException is thrown by GetManagedStatements when a SqliteCommand with more than one statement is executed over a direct remote TursoConnection that does not manage read-your-writes semantics and is not running inside an explicit SqliteTransaction. Multi-statement execution on a direct remote connection needs either session-level consistency (Read Your Writes=True) or a transaction to guarantee the statements see each other's effects.

Source

Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteCommand.cs:493

        }
    }

    private IReadOnlyList<ManagedSqliteStatement> GetManagedStatements()
    {
        var statements = ManagedSqliteStatementParser.Parse(CommandText);
        if (statements.Any(statement => statement.IsTransactionControl && !CanExecuteSavepointStatement(statement)))
        {
            throw new InvalidOperationException(
                "Transaction-control SQL is not supported on a managed SqliteConnection. "
                + "Use SqliteConnection.BeginTransaction and SqliteTransaction instead.");
        }

        if (statements.Count > 1
            && Connection!.IsDirectRemote
            && !Connection.ManagedReadYourWrites
            && Transaction is null)
        {
            throw new NotSupportedException(
                "Multi-statement SqliteCommand execution requires Read Your Writes=True "
                + "or an explicit SqliteTransaction on a direct remote connection.");
        }

        return statements;
    }

    private bool CanExecuteSavepointStatement(ManagedSqliteStatement statement)
    {
        if (Transaction is null)
            return false;

        if (statement.FirstKeyword is "SAVEPOINT" or "RELEASE")
            return true;

        if (statement.FirstKeyword != "ROLLBACK")
            return false;

View on GitHub (pinned to 6c72522679)

Solutions

  1. Enable Read Your Writes on the connection (set ManagedReadYourWrites/ReadYourWrites=True in the connection options)
  2. Wrap the command execution in an explicit SqliteTransaction (connection.BeginTransaction and assign it to command.Transaction)
  3. Split the multi-statement text into separate SqliteCommand executions
  4. Use a SqliteBatch (supported on direct remote/embedded replica connections) instead of a multi-statement command

Example fix

// before
using var cmd = conn.CreateCommand();
cmd.CommandText = "CREATE TABLE t(a); INSERT INTO t VALUES(1);";
cmd.ExecuteNonQuery(); // throws on direct remote without RYW

// after
cmd.CommandText = "CREATE TABLE t(a); INSERT INTO t VALUES(1);";
cmd.Transaction = conn.BeginTransaction();
cmd.ExecuteNonQuery();
cmd.Transaction.Commit();
Defensive patterns

Strategy: validation

Validate before calling

bool safe = conn.IsDirectRemote && !conn.ManagedReadYourWrites
    ? cmd.CommandText.Count(c => c == ';') <= 1 || cmd.Transaction != null
    : true;
if (!safe) throw new InvalidOperationException("Split statements, enable Read Your Writes, or use a transaction.");

Type guard

bool CanExecuteMultiStatement(SqliteConnection c, SqliteCommand cmd) =>
    !c.IsDirectRemote || c.ManagedReadYourWrites || cmd.Transaction is not null;

Try / catch

try { cmd.ExecuteNonQuery(); }
catch (NotSupportedException ex) when (ex.Message.Contains("Multi-statement"))
{
    cmd.Transaction = conn.BeginTransaction();
    cmd.ExecuteNonQuery();
    cmd.Transaction.Commit();
}

Prevention

When it happens

Trigger: Calling ExecuteReader/ExecuteNonQuery/ExecuteScalar on a SqliteCommand whose CommandText contains multiple statements separated by semicolons, while Connection.IsDirectRemote is true, Connection.ManagedReadYourWrites is false, and Command.Transaction is null.

Common situations: Developers porting ADO.NET code that runs multi-statement scripts (schema + seed data) against a Turso direct remote database; connection strings built without enabling managed read-your-writes; passing scripts through a command instead of a batch or transaction.

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/d9f1203c02bcdd94. Report an issue: GitHub.