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

Identical to the standard Cosmos sync-not-supported guard, but thrown specifically by the ReadItem-query path (ReadItemQueryingEnumerable.GetEnumerator). The ReadItem optimization performs a point read via the Cosmos SDK, which is async-only, so synchronous enumeration is blocked.

Source

Thrown at src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ReadItemQueryingEnumerable.cs:62

            _rootEntityType = rootEntityType;
            _readItemInfo = readItemInfo;
            _shaper = shaper;
            _contextType = contextType;
            _queryLogger = _cosmosQueryContext.QueryLogger;
            _standAloneStateManager = standAloneStateManager;
            _threadSafetyChecksEnabled = threadSafetyChecksEnabled;

            _cosmosContainer = rootEntityType.GetContainer()
                ?? throw new UnreachableException("Root entity type without a Cosmos container.");
            _cosmosPartitionKey = GeneratePartitionKey(
                rootEntityType, partitionKeyPropertyValues, _cosmosQueryContext.Parameters);
        }

        public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
            => new AsyncEnumerator(this, cancellationToken);

        public IEnumerator<T> GetEnumerator()
            => throw new InvalidOperationException(CosmosStrings.SyncNotSupported);

        IEnumerator IEnumerable.GetEnumerator()
            => GetEnumerator();

        public string ToQueryString()
        {
            TryGetResourceId(out var resourceId);
            return CosmosStrings.NoReadItemQueryString(resourceId, _cosmosPartitionKey);
        }

        private bool TryGetResourceId(out string resourceId)
        {
            var jsonIdDefinition = _rootEntityType.GetJsonIdDefinition();
            Check.DebugAssert(
                jsonIdDefinition != null,
                "Should not be using this enumerable if not using ReadItem, which needs an id definition.");

            var values = new List<object>(jsonIdDefinition.Properties.Count);

View on GitHub (pinned to dbf9771522)

Solutions

  1. Use async APIs: FirstAsync, SingleAsync, ToListAsync on the query.
  2. Ensure the consuming layer is async all the way up.
  3. Verify no synchronous helper enumerates the result before returning to an async context.

Example fix

// before
var blog = context.Blogs.WithPartitionKey(pk).Where(b => b.Id == id).First();
// after
var blog = await context.Blogs.WithPartitionKey(pk).Where(b => b.Id == id).FirstAsync();
Defensive patterns

Strategy: validation

Validate before calling

// Use async point-read APIs only
public async Task<Blog?> FindAsync(string pk, string id)
    => await context.Blogs.WithPartitionKey(pk).Where(b => b.Id == id).FirstOrDefaultAsync();

Prevention

When it happens

Trigger: Triggering a point-read (ReadItem) optimized query and then enumerating it synchronously (ToList, First, foreach). ReadItem optimization kicks in for PK lookups like Where(b => b.Id == id) combined with partition key.

Common situations: A query that the provider optimizes to a ReadItem (single document point read) being consumed via sync LINQ. Migrating a relational GetById that used First() synchronously.

Related errors


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