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

InMemoryDatabaseCreator.EnsureCreated (the synchronous path) looks up the CoreOptionsExtension's Seeder delegate. If Seeder is null but AsyncSeeder was provided (i.e. the user configured only UseAsyncSeeding), the sync code path has nothing to call and throws MissingSeeder. EF Core requires that if you seed data you provide both a sync and an async delegate, because the framework calls whichever matches the EnsureCreated/EnsureCreatedAsync method invoked.

Solutions

  1. Add UseSeeding with a delegate equivalent to the one supplied in UseAsyncSeeding.
  2. Call EnsureCreatedAsync() instead of EnsureCreated() so the async seed delegate is used.
  3. Provide both UseSeeding and UseAsyncSeeding delegates to cover both sync and async paths.

Example fix

// before — only async seeding configured
options.UseInMemoryDatabase("db")
      .UseAsyncSeeding((ctx, created, ct) => SeedAsync(ctx, ct));
// then later: ctx.Database.EnsureCreated();  // throws

// after — provide both sync and async seeders
options.UseInMemoryDatabase("db")
      .UseSeeding((ctx, created) => Seed(ctx))
      .UseAsyncSeeding((ctx, created, ct) => SeedAsync(ctx, ct));
Defensive patterns

Strategy: validation

Validate before calling

// Validate at startup: if AsyncSeeder is configured, ensure Seeder is too.
var coreExt = contextOptions.FindExtension<CoreOptionsExtension>();
if (coreExt?.AsyncSeeder != null && coreExt?.Seeder == null)
{
    throw new InvalidOperationException(
        "UseSeeding must be configured when UseAsyncSeeding is set, " +
        "because EnsureCreated() requires the sync seeder.");
}

Try / catch

try
{
    context.Database.EnsureCreated();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("seed delegate"))
{
    // Either add UseSeeding or switch to EnsureCreatedAsync
    await context.Database.EnsureCreatedAsync(cancellationToken);
}

Prevention

When it happens

Trigger: Configuring a model with UseAsyncSeeding(...) but not UseSeeding(...), then calling EnsureCreated() (synchronous). The creator finds no sync seeder and throws. Also triggered internally when EF Core calls the sync seed path during model finalization or migration.

Common situations: Setting up data seeding via UseAsyncSeeding in OnModelCreating or DbContextOptions but forgetting to add the sync equivalent. Calling context.Database.EnsureCreated() in a synchronous startup path (e.g. a console Main or a sync initializer). Migrating code that previously used only async seeding to a context where sync EnsureCreated is called.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/331ad75c3c6c6718. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.InMemory/Storage/Internal/InMemoryDatabaseCreator.cs:82

    ///     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 bool EnsureCreated()
    {
        var created = Database.EnsureDatabaseCreated();

        var coreOptionsExtension =
            _contextOptions.FindExtension<CoreOptionsExtension>()
            ?? new CoreOptionsExtension();

        var seed = coreOptionsExtension.Seeder;
        if (seed != null)
        {
            seed(_currentContext.Context, created);
        }
        else if (coreOptionsExtension.AsyncSeeder != null)
        {
            throw new InvalidOperationException(CoreStrings.MissingSeeder);
        }

        return created;
    }

    /// <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 async Task<bool> EnsureCreatedAsync(CancellationToken cancellationToken = default)
    {
        var created = Database.EnsureDatabaseCreated();

        var coreOptionsExtension =
            _contextOptions.FindExtension<CoreOptionsExtension>()
            ?? new CoreOptionsExtension();

View on GitHub (pinned to 3a2006ef56)