{"record":{"id":"ec8782675dc55cd7","repo":"dotnet/efcore","slug":"azure-cosmos-db-does-not-support-synchronous-i-o-ec8782","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseWrapper.cs","lineNumber":629,"sourceCode":"\n    private sealed class CosmosUpdateEntry\n    {\n        public required IUpdateEntry Entry { get; init; }\n        public required CosmosCudOperation Operation { get; init; }\n        public required string CollectionId { get; init; }\n        public required CosmosStructuralTypeSerializer Serializer { get; init; }\n    }\n\n    private sealed record Grouping(string ContainerId, PartitionKey PartitionKeyValue);\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    public override int SaveChanges(IList<IUpdateEntry> entries)\n        => throw new InvalidOperationException(CosmosStrings.SyncNotSupported);\n}\n","sourceCodeStart":611,"sourceCodeEnd":631,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseWrapper.cs#L611-L631","documentation":"The synchronous SaveChanges() override (CosmosDatabaseWrapper.cs:628-629) unconditionally throws because all Cosmos DB write operations (create, replace, delete) are asynchronous via the Microsoft.Azure.Cosmos SDK. There is no synchronous write path. This prevents deadlocks from sync-over-async wrapping.","triggerScenarios":"Calling context.SaveChanges() (without Async) on a Cosmos-backed DbContext. This directly throws before any entries are processed.","commonSituations":"Calling SaveChanges from synchronous application code, legacy libraries, or property setters. Copy-pasting relational save patterns. Using a shared repository abstraction with a sync Save method.","solutions":["Use the async overload: await context.SaveChangesAsync().","Make all repository/service methods async Task and propagate await up the call stack.","Refactor sync callers to async; avoid .GetAwaiter().GetResult() or .Result which can deadlock."],"exampleFix":"// before\npublic void Save(Blog blog)\n{\n    _context.Blogs.Add(blog);\n    _context.SaveChanges();\n}\n\n// after\npublic async Task SaveAsync(Blog blog)\n{\n    _context.Blogs.Add(blog);\n    await _context.SaveChangesAsync();\n}","handlingStrategy":"validation","validationCode":"// Ensure SaveChangesAsync is used. Enforce via async repository patterns.\nif (context.Database.ProviderName == \"Microsoft.EntityFrameworkCore.Cosmos\")\n{\n    // always: await context.SaveChangesAsync();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make all repository and service methods async Task.","Never call SaveChanges() (sync) on a Cosmos context.","Run a code-analysis check for sync SaveChanges calls on Cosmos DbContexts."],"tags":["cosmos","sync-not-supported","async","savechanges"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}