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 Migrator.ValidateMigrations when `Migrate`/`MigrateAsync` would run without a transaction (because a user transaction is already on the connection) while the configured execution strategy retries on failure. Retrying migrations need a transaction EF controls; an ambient user transaction makes that impossible.

Source

Thrown at src/EFCore.Relational/Migrations/Internal/Migrator.cs:374

            state.DatabaseLock?.Dispose();
            state.DatabaseLock = null;

            if (state.Transaction != null)
            {
                await state.Transaction.DisposeAsync().ConfigureAwait(false);
                state.Transaction = null;
            }

            await _connection.CloseAsync().ConfigureAwait(false);
        }
    }

    private void ValidateMigrations(bool useTransaction, string? targetMigration)
    {
        if (!useTransaction
            && _executionStrategy.RetriesOnFailure)
        {
            throw new NotSupportedException(RelationalStrings.TransactionSuppressedMigrationInUserTransaction);
        }

        if (_migrationsAssembly.Migrations.Count == 0)
        {
            _logger.MigrationsNotFound(this, _migrationsAssembly);
        }
        else if (_migrationsAssembly.ModelSnapshot == null)
        {
            _logger.ModelSnapshotNotFound(this, _migrationsAssembly);
        }
        else if (targetMigration == null
                 && RelationalResources.LogPendingModelChanges(_logger).WarningBehavior != WarningBehavior.Ignore
                 && HasPendingModelChanges())
        {
            var modelSource = (ModelSource)_currentContext.Context.GetService<IModelSource>();
#pragma warning disable EF1001 // Internal EF Core API usage.
            var newDesignTimeModel = modelSource.CreateModel(
                _currentContext.Context, _currentContext.Context.GetService<ModelCreationDependencies>(), designTime: true);

View on GitHub (pinned to dbf9771522)

Solutions

  1. Run `Migrate`/`MigrateAsync` before opening any transaction so EF owns the migration transaction.
  2. Drop the retrying execution strategy if you must keep the manual transaction.
  3. Use a separate DbContext/connection scope dedicated to migration.
  4. Avoid combining `EnableRetryOnFailure` with caller-managed transactions.

Example fix

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

Strategy: validation

Validate before calling

// Before Migrate with a retrying strategy, ensure no ambient transaction.
if (db.Database.CurrentTransaction is not null)
    throw new InvalidOperationException("Commit/close the ambient transaction before migrating with a retrying strategy.");
db.Database.Migrate();

Prevention

When it happens

Trigger: Opening your own transaction on the DbContext's connection and then calling `Migrate`/`MigrateAsync` while a retrying execution strategy (e.g. `EnableRetryOnFailure()`) is configured.

Common situations: Hosting code that wraps `Migrate` in a business transaction; transient-fault-handling configured globally with retries plus manual transactions; shared connection used for migrate + work.

Related errors


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