dotnet/efcore · error · InvalidOperationException
A synchronous store management operation was performed and…
Error message
A synchronous store management operation was performed and no synchronous seed delegate has been provided, however an asynchronous seed delegate was. Set 'UseSeeding' option with a delegate equivalent to the one supplied in 'UseAsyncSeeding'.
What it means
The synchronous Migrator path ran a store-management/migration operation. The configured DbContextOptions has an async seeder (UseAsyncSeeding) but no synchronous seeder (UseSeeding), so the sync path has nothing to call. EF requires the two delegates to be supplied as a matching pair so sync and async execution are both covered.
Solutions
- Add optionsBuilder.UseSeeding((ctx, anyOp) => { ... }) with a sync equivalent of your async seeder.
- Keep UseSeeding and UseAsyncSeeding logic in sync (call the same helper from both).
- If the operation must be async-only, switch the caller to the async API (MigrateAsync) so the sync path is never reached.
Example fix
// before
options.UseSqlServer(conn)
.UseAsyncSeeding(async (ctx, anyOp, ct) =>
{
await ctx.Products.AddAsync(new Product { Id = 1 }, ct);
await ctx.SaveChangesAsync(ct);
});
// after
options.UseSqlServer(conn)
.UseSeeding((ctx, anyOp) =>
{
ctx.Products.Add(new Product { Id = 1 });
ctx.SaveChanges();
})
.UseAsyncSeeding(async (ctx, anyOp, ct) =>
{
await ctx.Products.AddAsync(new Product { Id = 1 }, ct);
await ctx.SaveChangesAsync(ct);
}); Defensive patterns
Strategy: validation
Validate before calling
// At startup, assert the seeder pair is configured together
static void EnsureSeederPair(DbContextOptions opts)
{
var ext = opts.FindExtension<CoreOptionsExtension>();
if ((ext?.Seeder == null) ^ (ext?.AsyncSeeder == null))
throw new InvalidOperationException(
"Configure both UseSeeding and UseAsyncSeeding together.");
} Prevention
- Always configure UseSeeding and UseAsyncSeeding as a matched pair.
- Add a startup check that verifies both delegates are non-null.
- Prefer the async API (MigrateAsync) in async hosts to avoid the sync path entirely.
When it happens
Trigger: optionsBuilder.UseAsyncSeeding(...) was called without a matching UseSeeding(...), and a synchronous migration API is invoked (e.g. context.Database.Migrate(), Database.EnsureCreated(), or Migrator.Migrate on a sync code path).
Common situations: App configured only async seeding because the rest of the app is async, but a sync startup or test harness calls EnsureCreated/Migrate; upgrading from an older EF version that had a single seeding hook; copy-paste that lost the UseSeeding call.
Related errors
- A synchronous store management operation was performed and…
- A seed entity for entity type
- A seed entity for entity type
- A seed entity for entity type
- A synchronous store management operation was performed and…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/0cc1dba5d1b3a284.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Migrations/Internal/Migrator.cs:203
getCommands(), _connection, state, commitTransaction: useTransaction, MigrationTransactionIsolationLevel);
}
var coreOptionsExtension =
_contextOptions.FindExtension<CoreOptionsExtension>()
?? new CoreOptionsExtension();
var seed = coreOptionsExtension.Seeder;
if (seed != null)
{
if (!state.SeedingCompleted)
{
seed(context, state.AnyOperationPerformed);
state.SeedingCompleted = true;
}
}
else if (coreOptionsExtension.AsyncSeeder != null)
{
throw new InvalidOperationException(CoreStrings.MissingSeeder);
}
state.Transaction?.Commit();
return state.AnyOperationPerformed;
}
finally
{
state.DatabaseLock?.Dispose();
state.DatabaseLock = null;
state.Transaction?.Dispose();
state.Transaction = null;
_connection.Close();
}
}
/// <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 inView on GitHub (pinned to 3a2006ef56)