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
- Enable Read Your Writes on the connection (set ManagedReadYourWrites/ReadYourWrites=True in the connection options)
- Wrap the command execution in an explicit SqliteTransaction (connection.BeginTransaction and assign it to command.Transaction)
- Split the multi-statement text into separate SqliteCommand executions
- 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
- Enable Read Your Writes on direct remote connections by default
- Prefer SqliteBatch over multi-statement CommandText
- Keep schema scripts in separate single-statement commands or run them in a transaction
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
- Transaction must be a TursoTransaction.
- Transaction must be a SqliteTransaction.
- The transaction connection does not match the command connec
- The transaction has completed.
- Execute requires the command to have a transaction when the
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-09-06).
Data as JSON: /api/errors/d9f1203c02bcdd94.
Report an issue: GitHub.