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
Migrations cannot run inside a user-supplied transaction when either (a) any migration command is transaction-suppressed, or (b) the execution strategy retries on failure. Both require EF to control transaction boundaries, which is impossible while the caller holds its own transaction.
Solutions
- Do not open a user transaction around migrations; let EF manage the migration transaction.
- If you must retry, rely on the retrying execution strategy without an outer user transaction.
- Avoid TransactionSuppressed migration commands when running migrations programmatically inside app transactions.
- Move Migrate() outside any ambient TransactionScope before calling it.
Example fix
// before using var tx = context.Database.BeginTransaction(); await context.Database.MigrateAsync(); // throws // after await context.Database.MigrateAsync(); // run app logic / transactions after migrations complete
Defensive patterns
Strategy: validation
Validate before calling
bool hasUserTx = context.Database.CurrentTransaction is not null;
bool retries = context.Database.GetExecutionStrategy().RetriesOnFailure;
if (!hasUserTx)
{
context.Database.Migrate();
} Type guard
static bool CanMigrateInCurrentState(DbContext context, IEnumerable<MigrationCommand> cmds)
=> context.Database.CurrentTransaction is null
|| (!cmds.Any(c => c.TransactionSuppressed)
&& !context.Database.GetExecutionStrategy().RetriesOnFailure); Prevention
- Run migrations outside any user transaction or ambient TransactionScope.
- Do not combine a retrying execution strategy with manual transaction management for migrations.
- Keep startup migration calls before any application-level transaction work.
When it happens
Trigger: Calling Migrate()/MigrateAsync() (or the lower-level IMigrationCommandExecutor.ExecuteNonQuery) while a user transaction is active on the connection (connection.CurrentTransaction set, executionState.Transaction null), and at least one command has TransactionSuppressed or the execution strategy has RetriesOnFailure.
Common situations: Wrapping Database.Migrate() in an outer IDbContextTransaction; using SQL Server's retrying ExecutionStrategy together with migrations; manually opening a transaction before EnsureCreated/Migrate in startup code.
Related errors
- User transaction is not supported with a…
- A seed entity for entity type
- values were provided in CreateIndexOperations.IsDescending…
- Relational-specific methods can only be used when the…
- The computed column SQL has not been specified for the…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/808a87924c700d30.
Report an issue: GitHub.
Appendix: 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 3a2006ef56)