dotnet/efcore · error · InvalidOperationException

A synchronous store management operation was performed and n

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

During EnsureCreatedAsync, EF Core calls SeedDataAsync which requires an asynchronous seed delegate (UseAsyncSeeding). If you registered only a synchronous seed delegate via UseSeeding but not an async equivalent, the async seeding path has nothing to invoke and throws (CosmosDatabaseCreator.cs:252-259). Because Cosmos DB only supports async I/O, the sync seeder cannot be used here. The message instructs you to provide both delegates.

Source

Thrown at src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs:258

    ///     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 SeedDataAsync(
        bool created,
        CancellationToken cancellationToken = default)
    {
        var coreOptionsExtension =
            _contextOptions.FindExtension<CoreOptionsExtension>();

        if (coreOptionsExtension?.AsyncSeeder is not null)
        {
            await coreOptionsExtension.AsyncSeeder(_currentContext.Context, created, cancellationToken).ConfigureAwait(false);
        }
        else if (coreOptionsExtension?.Seeder is not null)
        {
            throw new InvalidOperationException(CoreStrings.MissingSeeder);
        }
    }

    /// <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 Task<bool> EnsureDeletedAsync(CancellationToken cancellationToken = default)
        => _cosmosClient.DeleteDatabaseAsync(cancellationToken);

    /// <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>

View on GitHub (pinned to dbf9771522)

Solutions

  1. Register both delegates with equivalent logic: optionsBuilder.UseSeeding((ctx, created) => SeedData(ctx, created)) and optionsBuilder.UseAsyncSeeding(async (ctx, created, ct) => await SeedDataAsync(ctx, created, ct)).
  2. For Cosmos-only apps, register only UseAsyncSeeding (the async path is what runs).
  3. Ensure the sync and async delegates perform the same seeding work to keep behavior consistent across sync/async entry points.

Example fix

// before
optionsBuilder.UseSeeding((ctx, created) =>
{
    ctx.Blogs.Add(new Blog { Url = "http://sample.com" });
    ctx.SaveChanges();
});

// after
optionsBuilder.UseSeeding((ctx, created) =>
{
    ctx.Blogs.Add(new Blog { Url = "http://sample.com" });
    ctx.SaveChanges();
});
optionsBuilder.UseAsyncSeeding(async (ctx, created, ct) =>
{
    ctx.Blogs.Add(new Blog { Url = "http://sample.com" });
    await ctx.SaveChangesAsync(ct);
});
Defensive patterns

Strategy: validation

Validate before calling

// After configuring options, verify both seeders are registered when using Cosmos.
var coreExt = dbContextOptions.FindExtension<CoreOptionsExtension>();
if (coreExt?.Seeder is not null && coreExt?.AsyncSeeder is null)
    throw new InvalidOperationException("UseSeeding is set but UseAsyncSeeding is missing; Cosmos requires the async seeder.");

Prevention

When it happens

Trigger: Configuring optionsBuilder.UseSeeding((ctx, created) => { ... }) without a matching optionsBuilder.UseAsyncSeeding((ctx, created, ct) => ...), then calling context.Database.EnsureCreatedAsync(). The Cosmos provider's SeedDataAsync checks for AsyncSeeder first; if null but Seeder exists, it throws.

Common situations: Following a relational-provider tutorial that only registers UseSeeding and switching to Cosmos. Registering seed logic in only the sync overload during migration to async. Using a shared seeding helper that only provides the sync delegate.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/7a5bef48a24a904c. Report an issue: GitHub.