dotnet/efcore · error · NotSupportedException

User transaction is not supported with a…

Error message

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

What it means

ValidateMigrations throws when the caller asked to run migrations without an explicit transaction (useTransaction == false, i.e. a 'transaction-suppressed' migration) AND the configured execution strategy retries on failure. Retrying individual commands outside a transaction can leave the database half-migrated, so EF refuses the unsafe combination rather than risk inconsistency.

Solutions

  1. Run the migration inside a transaction (default) — remove the useTransaction:false / suppression.
  2. If you must suppress transactions, switch to a non-retrying execution strategy (the default ExecutionStrategy) for migrations.
  3. For one-off long DDL, split it into smaller migrations that fit in a transaction instead of suppressing.

Example fix

// before
options.UseSqlServer(conn)
       .EnableRetryOnFailure();            // retrying strategy
await db.Database.MigrateAsync(cancellationToken); // fine
// but somewhere: migrator.Migrate(useTransaction: false)  -> throws

// after — keep transactions on with retries
await db.Database.MigrateAsync(cancellationToken);
// or, if you truly need no transaction, drop retries for this run:
options.UseSqlServer(conn); // default, non-retrying strategy
Defensive patterns

Strategy: validation

Validate before calling

// Before migrating, detect the unsafe combination
static bool IsRetrying(DbContext db)
    => db.GetService<IExecutionStrategy>() is { RetriesOnFailure: true };

if (IsRetrying(db) && suppressTransaction)
    throw new InvalidOperationException(
        "Retrying strategy cannot run with transaction suppression.");

Type guard

null

Prevention

When it happens

Trigger: Migrator.Migrate/MigrateAsync is invoked with useTransaction:false (or via a context configured with TransactionSuppressed behavior) while options.UseSqlServer(...).UseExecutionStrategy(s => new SqlServerRetryingExecutionStrategy(s)) or any strategy whose RetriesOnFailure is true is registered.

Common situations: Enabling retry-on-failure for Azure SQL then trying to run migrations outside a transaction to work around a long-running DDL statement; mixing EnableRetryOnFailure with a custom Migrate call that passes useTransaction:false; legacy migration runner that suppressed transactions.

Related errors


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

Appendix: 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 3a2006ef56)