dotnet/efcore · error · NotSupportedException

User transaction is not supported with a TransactionSuppress

Error message

User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy.

What it means

Thrown by the synchronous MigrationCommandExecutor.ExecuteNonQuery when there is an ambient user transaction on the connection AND either a migration command is marked `TransactionSuppressed` or the configured execution strategy retries on failure. Retrying or transaction-suppressed migrations cannot be coordinated with a caller-managed transaction.

Source

Thrown at src/EFCore.Relational/Migrations/Internal/MigrationCommandExecutor.cs:52

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public virtual int ExecuteNonQuery(
        IReadOnlyList<MigrationCommand> migrationCommands,
        IRelationalConnection connection,
        MigrationExecutionState executionState,
        bool commitTransaction,
        IsolationLevel? isolationLevel = null)
    {
        var inUserTransaction = connection.CurrentTransaction is not null && executionState.Transaction == null;
        if (inUserTransaction
            && (migrationCommands.Any(x => x.TransactionSuppressed) || executionStrategy.RetriesOnFailure))
        {
            throw new NotSupportedException(RelationalStrings.TransactionSuppressedMigrationInUserTransaction);
        }

        using var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled);

        return executionStrategy.Execute(
            (migrationCommands, connection, inUserTransaction, executionState, commitTransaction, isolationLevel),
            static (_, s) => Execute(
                s.migrationCommands,
                s.connection,
                s.executionState,
                beginTransaction: !s.inUserTransaction,
                commitTransaction: !s.inUserTransaction && s.commitTransaction,
                s.isolationLevel),
            verifySucceeded: null);
    }

    private static int Execute(
        IReadOnlyList<MigrationCommand> migrationCommands,

View on GitHub (pinned to dbf9771522)

Solutions

  1. Do not open your own transaction around `Migrate`; let EF own the migration transaction.
  2. If you need a retrying strategy, remove the manual `BeginTransaction` call before migrating.
  3. If a migration must run outside a transaction, ensure you are NOT also in a user transaction (call `Migrate` before `BeginTransaction`).
  4. Separate migration application from your business-logic transaction entirely.

Example fix

// before
using var tx = db.Database.BeginTransaction();
db.Database.Migrate();
// after
db.Database.Migrate();
using var tx = db.Database.BeginTransaction();
Defensive patterns

Strategy: validation

Validate before calling

// Never migrate inside a user transaction; verify before calling sync Migrate.
if (db.Database.CurrentTransaction is not null)
    throw new InvalidOperationException("Close/commit the ambient transaction before calling Migrate.");
db.Database.Migrate();

Prevention

When it happens

Trigger: Calling `migrator.Migrate(...)` / `MigrateAsync` (or raw `IMigrationCommandExecutor.ExecuteNonQuery`) while you have already begun a transaction on the same `IRelationalConnection`, combined with a retrying execution strategy (e.g. SqlServer `EnableRetryOnFailure`) or a migration whose builder used `SuppressTransaction()`.

Common situations: Wrapping `Database.Migrate()` inside your own `Database.BeginTransaction()`; using `EnableRetryOnFailure` together with explicit transactions; custom hosting code that opens a transaction before seeding/migrating.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/808a87924c700d30. Report an issue: GitHub.