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
- Run the migration inside a transaction (default) — remove the useTransaction:false / suppression.
- If you must suppress transactions, switch to a non-retrying execution strategy (the default ExecutionStrategy) for migrations.
- 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
- Do not combine EnableRetryOnFailure with transaction-suppressed migrations.
- Keep retry strategies for runtime CRUD, not for DDL-heavy migrations, or accept transactions.
- Document the migration transaction policy in the project's runbook.
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
- User transaction is not supported with a…
- A synchronous store management operation was performed and…
- Relational-specific methods can only be used when the…
- The computed column SQL has not been specified for the…
- The default value has not been specified for the column
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)