Updated October 2026 for .NET 10 (LTS) and EF Core 10.

If Entity Framework Core stops with the error below, the database call failed for a reason that is usually temporary: a dropped connection, a busy server, a failover, or a cloud database waking up. The fix is to turn on EF Core’s built-in retry logic with EnableRetryOnFailure(). This guide shows where to add it, which options to use, and the one case (manual transactions) where you need extra code.

The error

System.InvalidOperationException: An exception has been raised that is likely due to a transient failure. Consider enabling transient error resiliency by adding 'EnableRetryOnFailure()' to the 'UseSqlServer' call.

Why it happens

A transient error is a short-lived failure that usually succeeds if you simply try again. Common causes:

  • Brief network drops between your app and the database
  • Azure SQL or other managed databases moving, failing over or throttling
  • A serverless database that was paused and is still starting up
  • Connection pool or server resource limits during traffic spikes

EF Core recognises these errors but, by default, does not retry them. It throws this exception to tell you that a retry strategy would probably have succeeded.

Fix 1: Enable retries in Program.cs (recommended)

In .NET 10 you register your DbContext in Program.cs. Pass a second lambda to UseSqlServer:

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(connectionString, sqlOptions =>
    {
        sqlOptions.EnableRetryOnFailure(
            maxRetryCount: 5,                        // try up to 5 more times
            maxRetryDelay: TimeSpan.FromSeconds(30), // longest wait between tries
            errorNumbersToAdd: null);                // extra SQL error numbers to retry
    }));

var app = builder.Build();

Calling EnableRetryOnFailure() with no arguments also works and uses EF Core’s defaults. The waits between attempts grow with each retry (exponential backoff), so a struggling server is not flooded with requests.

Fix 2: Enable retries inside the DbContext

If you configure the context in OnConfiguring instead (common in console apps and worker services), add the same option there:

public class AppDbContext : DbContext
{
    public DbSet<Order> Orders => Set<Order>();

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(
                "Server=.;Database=Shop;Trusted_Connection=True;TrustServerCertificate=True",
                sql => sql.EnableRetryOnFailure(
                    maxRetryCount: 5,
                    maxRetryDelay: TimeSpan.FromSeconds(30),
                    errorNumbersToAdd: null));
        }
    }
}

Keep real connection strings in configuration or a secret store such as Azure Key Vault, not in code.

Other databases

Most EF Core providers have the same option. For PostgreSQL (Npgsql) the third parameter is named errorCodesToAdd:

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(connectionString, npgsql =>
        npgsql.EnableRetryOnFailure(
            maxRetryCount: 5,
            maxRetryDelay: TimeSpan.FromSeconds(30),
            errorCodesToAdd: null)));

For Azure SQL, use UseAzureSql(...), which exposes the same EnableRetryOnFailure option.

Important: manual transactions need an execution strategy

Once retries are on, code that starts its own transaction with BeginTransaction() throws an InvalidOperationException. EF Core cannot safely retry half of your transaction, so you must wrap the whole unit of work in an execution strategy:

var strategy = db.Database.CreateExecutionStrategy();

await strategy.ExecuteAsync(async () =>
{
    db.ChangeTracker.Clear(); // start each attempt clean

    await using var transaction = await db.Database.BeginTransactionAsync();

    var order = await db.Orders.FirstAsync(o => o.Id == orderId);
    order.Status = "Paid";
    db.Payments.Add(new Payment { OrderId = orderId, Amount = order.Total });

    await db.SaveChangesAsync();
    await transaction.CommitAsync();
});

Everything inside ExecuteAsync is retried as one block. Load entities inside the block, as shown, so a retry does not reuse changes from a failed attempt. More detail: Connection resiliency for transactions in EF Core.

Still failing after retries? Check these

  • Command timeouts are not retried by default. On SQL Server, a timeout is error number -2. Add it with errorNumbersToAdd: new[] { -2 } only if the operation is safe to repeat (idempotent).
  • The error is not actually transient. Wrong passwords, a blocked firewall or a missing database will fail every time. Read the inner exception.
  • Serverless or paused databases can take longer to wake than your retry window. Increase maxRetryDelay or keep the database warm.
  • Long-running queries may need a higher CommandTimeout or a better index rather than more retries.

FAQ

Does EnableRetryOnFailure slow down my app?

No. It only adds work when a transient error happens. Successful calls run exactly as before.

Can I write my own retry logic instead?

Yes. You can register a custom execution strategy, or use Polly for non-EF calls. See Database connection resiliency in EF Core and Implement the retry pattern in C#. For most apps, the built-in strategy is enough.

Do I need extra NuGet packages?

No. EnableRetryOnFailure is part of the provider package you already use, such as Microsoft.EntityFrameworkCore.SqlServer 10.x or Npgsql.EntityFrameworkCore.PostgreSQL 10.x.

Related

Sources: Microsoft Learn: Connection resiliency in EF Core · Microsoft Learn: Resilient EF Core SQL connections

4 thoughts on “Fix: “An exception has been raised that is likely due to a transient failure” – EnableRetryOnFailure in EF Core 10”

  1. Hi, i tried utilizing one of your methods above,but now i am getting evaluation timed out. Here is my method

    public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config)
    {
    var connectionString = config["mysqlconnection:connectionString"];
    //services.AddDbContext(o => o.UseMySql(connectionString));

    services.AddDbContext(options =>
    {
    options.UseMySql(connectionString,
    mySqlOptionsAction: MySqlOptions =>
    {
    MySqlOptions.EnableRetryOnFailure(
    maxRetryCount: 10,
    maxRetryDelay: TimeSpan.FromSeconds(30),
    errorNumbersToAdd: null);
    });
    });

    }

    1. Hi Kelvin- Thanks for your query. There could be multiple reasons for this. If possible try to use the latest MySQL NuGet packages(Old few version had time out issue) and please re-verify connection string supplied.

Leave a Reply

Your email address will not be published. Required fields are marked *