tursodatabase/turso · error · ArgumentException
Transaction must be a SqliteTransaction.
Error message
Transaction must be a SqliteTransaction.
What it means
SqliteCommand implements DbCommand, whose constructor accepts any DbTransaction; the provider understands only SqliteTransaction (its own type that talks to the native engine), so a non-null transaction of another ADO.NET provider is rejected with ArgumentException. Null is allowed and means 'not enlisted'. The check happens at construction so the failure surfaces before execution inside native code.
Source
Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteCommand.cs:52
}
public SqliteCommand(string? commandText, SqliteConnection? connection)
: this(commandText)
{
Connection = connection;
}
public SqliteCommand(string? commandText, SqliteConnection? connection, SqliteTransaction? transaction)
: this(commandText, connection)
{
Transaction = transaction;
}
public SqliteCommand(string? commandText, SqliteConnection? connection, DbTransaction? transaction)
: this(commandText, connection)
{
Transaction = transaction as SqliteTransaction
?? (transaction is null ? null : throw new ArgumentException("Transaction must be a SqliteTransaction.", nameof(transaction)));
}
[AllowNull]
public override string CommandText
{
get => _commandText;
set
{
ThrowIfReaderOpen(nameof(CommandText));
_commandText = value ?? string.Empty;
}
}
public override int CommandTimeout
{
get => _commandTimeout;
set
{View on GitHub (pinned to 6c72522679)
Solutions
- Pass the SqliteTransaction returned by sqliteConn.BeginTransaction().
- Pattern-match before passing: only forward transactions that are SqliteTransaction.
- In generic helpers, keep connection+transaction provider pairs together (DbProviderFactory) so the right types flow.
Example fix
// before DbTransaction tx = GetUnitOfWorkTransaction(); // e.g. a SqlTransaction from SQL Server using var cmd = new SqliteCommand(sql, conn, tx); // throws: must be a SqliteTransaction // after using var tx = conn.BeginTransaction(); // SqliteTransaction from the same connection using var cmd = new SqliteCommand(sql, conn, tx);
Defensive patterns
Strategy: type-guard
Validate before calling
if (transaction is not null and not SqliteTransaction)
throw new ArgumentException("Transaction must come from a SqliteConnection.");
var cmd = new SqliteCommand(sql, conn, transaction as SqliteTransaction); Type guard
static SqliteTransaction? AsSqlite(DbTransaction? tx) => tx switch {
null => null,
SqliteTransaction s => s,
_ => throw new ArgumentException("Transaction must be a SqliteTransaction.")
}; Prevention
- Begin transactions from the same SqliteConnection the command uses.
- In generic code, keep provider pairs (connection+transaction) together via DbProviderFactory.
- Never pass one provider's transaction into another provider's command.
When it happens
Trigger: new SqliteCommand(sql, conn, tx) where tx came from another provider (e.g., SqlTransaction) or from a different connection; generic ADO.NET helpers that thread DbTransaction through to any command; DI wiring that injects the wrong DbTransaction.
Common situations: Multi-database unit-of-work code passing one provider's transaction to another's command; copy-paste from System.Data.SqlClient samples; provider-agnostic data layers that lost type pairing.
Related errors
- Transaction must be a TursoTransaction.
- Batch command must be a TursoBatchCommand.
- Connection must be a TursoConnection.
- Parameter must be of type TursoParameter
- Connection must be a SqliteConnection.
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20).
Data as JSON: /api/errors/6751624d6e97970d.
Report an issue: GitHub.