dotnet/efcore · error · InvalidOperationException

Azure Cosmos DB does not support synchronous I/O. Make sure…

Error message

Azure Cosmos DB does not support synchronous I/O. Make sure to use and correctly await only async methods when using Entity Framework Core to access Azure Cosmos DB.

What it means

The Cosmos batch executor's synchronous SaveChanges override throws because the Cosmos SDK is async-only. Any call to the sync SaveChanges on a Cosmos-backed DbContext routes here and fails immediately.

Solutions

  1. Call await dbContext.SaveChangesAsync(cancellationToken) instead.
  2. Make the calling method async to propagate the await.
  3. If you control the abstraction, expose only async save methods to prevent sync misuse.

Example fix

// before
dbContext.SaveChanges();

// after
await dbContext.SaveChangesAsync();
Defensive patterns

Strategy: validation

Validate before calling

if (dbContext.Database.ProviderName == "Microsoft.EntityFrameworkCore.Cosmos")
{
    throw new InvalidOperationException("Use SaveChangesAsync for Cosmos.");
}
dbContext.SaveChanges();

Prevention

When it happens

Trigger: Calling dbContext.SaveChanges() (sync) on a Cosmos provider. Happens with sync repositories, sync test helpers, or library code that calls SaveChanges without an async overload.

Common situations: Reusing a sync generic repository against Cosmos. Legacy sync code paths. Libraries that hard-code SaveChanges().

Related errors


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

Appendix: source

Thrown at src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseWrapper.cs:629

    private sealed class CosmosUpdateEntry
    {
        public required IUpdateEntry Entry { get; init; }
        public required CosmosCudOperation Operation { get; init; }
        public required string CollectionId { get; init; }
        public required CosmosStructuralTypeSerializer Serializer { get; init; }
    }

    private sealed record Grouping(string ContainerId, PartitionKey PartitionKeyValue);

    /// <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 override int SaveChanges(IList<IUpdateEntry> entries)
        => throw new InvalidOperationException(CosmosStrings.SyncNotSupported);
}

View on GitHub (pinned to 3a2006ef56)