tursodatabase/turso · error · ArgumentException

Transaction must be a TursoTransaction.

Error message

Transaction must be a TursoTransaction.

What it means

The DbTransaction setter on TursoCommand only accepts TursoTransaction (TursoCommand.cs:86-98) — the transaction object begun on the same TursoConnection. A transaction from another provider, or from a different connection, cannot be attached and throws ArgumentException; assigning null detaches cleanly.

Source

Thrown at bindings/dotnet/src/Turso.Data/TursoCommand.cs:96

    protected override DbParameterCollection DbParameterCollection => _parameterCollection;

    public new virtual TursoParameterCollection Parameters => _parameterCollection;


    protected override DbTransaction? DbTransaction
    {
        get => _transaction;
        set
        {
            if (value is null)
            {
                _transaction = null;
                return;
            }

            _transaction = value as TursoTransaction
                           ?? throw new ArgumentException("Transaction must be a TursoTransaction.", nameof(value));
        }
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        _statement?.Dispose();
    }

    public override void Cancel()
    {
    }

    public override int ExecuteNonQuery()
    {
        if (_connection?.IsRemote == true)
            return ExecuteRemoteNonQueryAsync(CancellationToken.None).GetAwaiter().GetResult();

View on GitHub (pinned to c1e5928725)

Solutions

  1. Begin the transaction on the TursoConnection and assign that: cmd.Transaction = await tursoConn.BeginTransactionAsync(ct);
  2. When rebinding a command to a different connection, first set cmd.Transaction = null, then assign the new TursoConnection and its transaction.
  3. Keep connection, command, and transaction objects sourced from one provider and one connection instance.

Example fix

// before
cmd.Connection = tursoConn;
cmd.Transaction = oldSqlTransaction; // throws ArgumentException

// after
using var tx = tursoConn.BeginTransaction();
cmd.Connection = tursoConn;
cmd.Transaction = tx;
Defensive patterns

Strategy: type-guard

Validate before calling

if (tx is not null && tx is not TursoTransaction)
    throw new InvalidOperationException("Transaction belongs to a different provider/connection.");

Type guard

static bool IsTursoTransaction(DbTransaction? t) => t is null || t is TursoTransaction;

Try / catch

try
{
    cmd.Transaction = tx;
}
catch (ArgumentException ex) when (ex.ParamName == "value")
{
    // tx is foreign; begin a fresh transaction on the TursoConnection instead.
}

Prevention

When it happens

Trigger: cmd.Transaction = sqlTransaction; where sqlTransaction came from SqlConnection.BeginTransaction(); or reassigning a command to a new connection while it still holds a transaction from the old one.

Common situations: Refactors that swap the connection in a helper but keep the old transaction; cross-provider code that shares System.Data.Common objects; partial migration where one branch of code still uses SqlClient transactions.

Related errors


AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-20). Data as JSON: /api/errors/5b714a1ba8421c39. Report an issue: GitHub.