{"record":{"id":"23e61ac947ce6b10","repo":"dotnet/efcore","slug":"user-transaction-is-not-supported-with-a-transacti-23e61a","errorCode":null,"errorMessage":"User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy.","messagePattern":"User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Migrations/Internal/Migrator.cs","lineNumber":374,"sourceCode":"            state.DatabaseLock?.Dispose();\n            state.DatabaseLock = null;\n\n            if (state.Transaction != null)\n            {\n                await state.Transaction.DisposeAsync().ConfigureAwait(false);\n                state.Transaction = null;\n            }\n\n            await _connection.CloseAsync().ConfigureAwait(false);\n        }\n    }\n\n    private void ValidateMigrations(bool useTransaction, string? targetMigration)\n    {\n        if (!useTransaction\n            && _executionStrategy.RetriesOnFailure)\n        {\n            throw new NotSupportedException(RelationalStrings.TransactionSuppressedMigrationInUserTransaction);\n        }\n\n        if (_migrationsAssembly.Migrations.Count == 0)\n        {\n            _logger.MigrationsNotFound(this, _migrationsAssembly);\n        }\n        else if (_migrationsAssembly.ModelSnapshot == null)\n        {\n            _logger.ModelSnapshotNotFound(this, _migrationsAssembly);\n        }\n        else if (targetMigration == null\n                 && RelationalResources.LogPendingModelChanges(_logger).WarningBehavior != WarningBehavior.Ignore\n                 && HasPendingModelChanges())\n        {\n            var modelSource = (ModelSource)_currentContext.Context.GetService<IModelSource>();\n#pragma warning disable EF1001 // Internal EF Core API usage.\n            var newDesignTimeModel = modelSource.CreateModel(\n                _currentContext.Context, _currentContext.Context.GetService<ModelCreationDependencies>(), designTime: true);","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Migrations/Internal/Migrator.cs#L356-L392","documentation":"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.","triggerScenarios":"Opening your own transaction on the DbContext's connection and then calling `Migrate`/`MigrateAsync` while a retrying execution strategy (e.g. `EnableRetryOnFailure()`) is configured.","commonSituations":"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.","solutions":["Run `Migrate`/`MigrateAsync` before opening any transaction so EF owns the migration transaction.","Drop the retrying execution strategy if you must keep the manual transaction.","Use a separate DbContext/connection scope dedicated to migration.","Avoid combining `EnableRetryOnFailure` with caller-managed transactions."],"exampleFix":"// before\noptions.UseSqlServer(cs).EnableRetryOnFailure();\nusing var tx = db.Database.BeginTransaction();\ndb.Database.Migrate();\n// after\noptions.UseSqlServer(cs).EnableRetryOnFailure();\ndb.Database.Migrate();\nusing var tx = db.Database.BeginTransaction();","handlingStrategy":"validation","validationCode":"// Before Migrate with a retrying strategy, ensure no ambient transaction.\nif (db.Database.CurrentTransaction is not null)\n    throw new InvalidOperationException(\"Commit/close the ambient transaction before migrating with a retrying strategy.\");\ndb.Database.Migrate();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run `Migrate`/`MigrateAsync` outside any user transaction when `EnableRetryOnFailure` is configured.","Use a dedicated DbContext for migration in startup.","Do not wrap migration in a business transaction."],"tags":["efcore","migrations","transactions","execution-strategy","relational"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}