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

Same SyncNotSupported guard as the regular QueryingEnumerable, but on the ReadItem (point-lookup) path. When EF optimizes a query to a single ReadItemAsync call, the ReadItemQueryingEnumerable still implements IEnumerator<T> GetEnumerator to throw InvalidOperationException on any synchronous enumeration.

Solutions

  1. Switch all lookup paths to async: await ...FirstOrDefaultAsync / FindAsync.
  2. Expose IAsyncEnumerable<T> from repository helpers instead of IQueryable<T>.
  3. Static-analyze the codebase for sync LINQ-to-IQueryable call sites.

Example fix

// before
var user = db.Users.FirstOrDefault(u => u.Id == id);
// after
var user = await db.Users.FirstOrDefaultAsync(u => u.Id == id);
Defensive patterns

Strategy: validation

Validate before calling

static async Task<T?> FindAsync<T>(DbSet<T> set, object[] keys, CancellationToken ct)
    where T : class
    => await set.FindAsync(keys, ct).AsTask().ConfigureAwait(false);

Prevention

When it happens

Trigger: Synchronous enumeration of a query that EF compiled down to a ReadItem (e.g. Find-like lookup by id and partition key), or calling .ToList()/.First() on a query that selects a single entity by its id.

Common situations: Wrapping a point-lookup helper that returns IQueryable and the caller enumerates synchronously; reusing sync repository methods against Cosmos.

Related errors


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

Appendix: 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 3a2006ef56)