Repository navigation
Troubleshooting
Common errors and how to fix them. For behavioural differences between the emulator and real Azure Cosmos DB, see Known Limitations.
Symptom: Compile error — CreateClient(), WrapClient(), or CreateRouter() are no longer accessible on FakeCosmosHandler.
Cause: These methods were made internal in v3.0.0 and replaced by the InMemoryCosmos API.
Fix: Replace manual FakeCosmosHandler wiring with InMemoryCosmos:
// Before (2.x)
var handler = new FakeCosmosHandler(container);
var client = handler.CreateClient();
// After (3.0.0)
using var cosmos = InMemoryCosmos.Create("my-container", "/pk");
var client = cosmos.Client;See the full Migration Guide for multi-container, custom options, and fault injection patterns.
Symptom: CreateItemAsync, UpsertItemAsync, or their stream variants throw:
Item must have an 'id' property (case-sensitive, lowercase). If your C# model uses PascalCase 'Id', ensure CosmosClientOptions.Serializer is configured with camelCase naming (e.g. CosmosJsonDotNetSerializer with CamelCasePropertyNamesContractResolver).
Cause: The Cosmos SDK serializes your C# object to JSON before sending it. If your model has public string Id { get; set; } (PascalCase), the default serializer produces { "Id": "..." } — but Cosmos requires lowercase "id".
Fix (recommended): Add [JsonProperty("id")] on the property:
using Newtonsoft.Json;
[JsonProperty("id")]
public string Id { get; set; }This is the simplest approach and works with all integration approaches.
Alternative fix: Configure CosmosClientOptions.Serializer with a camelCase contract resolver. Note that CosmosJsonDotNetSerializer is not part of the public SDK — you need to supply your own CosmosSerializer implementation, or copy the one from the Azure Cosmos DB samples:
var client = new CosmosClient(connectionString, new CosmosClientOptions
{
Serializer = new MyCustomCosmosSerializer(new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
})
});This error applies equally to all integration approaches (
InMemoryCosmos.Create(),FakeCosmosHandler, and Dependency Injection methods) and the real Azure Cosmos DB service. See Getting Started — serialization note and Setup Guide — serialization for more context.
Symptom: NullReferenceException when calling CRUD operations through FakeCosmosHandler.
Cause: Usually the same root cause as above — the serialized JSON doesn't contain "id" (lowercase), so partition key extraction or document indexing fails.
Fix: Apply the [JsonProperty("id")] fix or camelCase serializer described above.
Symptom: GetItemQueryIterator or LINQ queries return no items, even though items were inserted.
Possible causes:
-
Partition key path mismatch. The container was created with a different partition key path than your production container. For example, your production container uses
/customerIdbut the test uses the default/id. -
Cross-partition query not enabled. By default, queries target a single partition. If you pass a
PartitionKeyinQueryRequestOptions, only items in that partition are returned. Omit the partition key to run a cross-partition query. -
Serialization mismatch. Items were inserted with one casing but queried with another. Ensure serializer configuration is consistent across all operations.
Fix: Verify the partition key path matches your production configuration:
// Must match your Azure Cosmos container's partition key path
using var cosmos = InMemoryCosmos.Create("orders", "/customerId");For a full list of supported query syntax, see SQL Queries.
v3.0.0 note:
CreateRouter()is nowinternal. UseInMemoryCosmos.Builder().AddContainer(...)instead. The error message now returns a 404CosmosExceptionwith the list of available containers.
Symptom: CosmosException (404) when accessing a container:
Container 'xxx' not found. Available containers: a, b, c.
Cause: Your production code calls client.GetContainer("db", "xxx"), but "xxx" is not registered.
Fix (3.0.0): Add the missing container to the builder:
using var cosmos = InMemoryCosmos.Builder()
.AddContainer("orders", "/customerId")
.AddContainer("customers", "/id")
.AddContainer("xxx", "/id") // ← add this
.Build();See Setup Guide — Direct Instantiation for the full pattern.
Symptom: InMemoryChangeFeedProcessor doesn't invoke the delegate after inserting items.
Cause: The processor must be started explicitly and polls on a 50 ms interval internally. If your test completes before the poll cycle runs, the delegate won't fire.
Fix: Ensure you call StartAsync() and allow time for the poll cycle:
await processor.StartAsync();
// ... insert items ...
await Task.Delay(500); // allow poll cycle to complete
await processor.StopAsync();The in-memory change feed has several known behavioural differences from real Cosmos DB, including FeedRange scoping and the stream handler variant. See Features — Change Feed for supported functionality.
Symptom: NotSupportedException when running a SQL query:
Failed to parse Cosmos SQL query: SELECT ...
Cause: The built-in SQL parser doesn't support the query syntax you're using. While it covers 120+ functions and most common patterns, some advanced or rarely-used Cosmos SQL syntax may not yet be implemented.
Fix: Check the SQL Queries page for the full list of supported clauses, operators, and functions. If your query uses unsupported syntax, consider:
- Filing an issue to request support.
- Rewriting the query using supported syntax.
- Falling back to LINQ-based queries if applicable.
Symptom: Items with a TTL (time-to-live) are still returned by queries after they should have expired.
Cause: The emulator uses lazy TTL eviction — expired items are removed during reads and queries, not proactively on a background timer. This differs from real Cosmos DB, which evicts items in the background.
Fix: This is expected behaviour. Expired items are filtered out of query results and point reads. If you need to verify TTL expiry in tests, insert the item, advance past the TTL duration with Task.Delay, and then confirm the item is no longer returned. See Known Limitations for details.
Symptom: Calling .ToFeedIterator() on a LINQ query throws:
ArgumentOutOfRangeException: ToFeedIterator is only supported on Cosmos LINQ query operations
Cause: When using a raw container directly (not via FakeCosmosHandler), GetItemLinqQueryable<T>() returns a standard LINQ-to-Objects queryable. The SDK's .ToFeedIterator() only works on queryables created by its own CosmosLinqQueryProvider.
Fix: All recommended approaches (InMemoryCosmos.Create(), UseInMemoryCosmosDB(), UseInMemoryCosmosContainers()) use FakeCosmosHandler internally, which means .ToFeedIterator() works as-is. If you see this error, you're likely using an internal class directly. Migrate to one of the recommended patterns.
See How Does ToFeedIterator() Work? for details.
Symptom: InvalidOperationException during test setup mentioning "SDK compatibility check failed":
SDK compatibility check failed (v3.x.x): expected 3 items from basic query but got 0. The Cosmos SDK may have changed its internal HTTP contract.
Cause: FakeCosmosHandler.VerifySdkCompatibilityAsync() runs a suite of checks to verify that the installed Cosmos SDK version is compatible with the handler's HTTP interception layer. A failure means the SDK version you're using has changed its internal HTTP contract in a way that FakeCosmosHandler doesn't yet support.
Fix:
- Check you're using a supported SDK version (3.58.0+).
- Update to the latest version of
CosmosDB.InMemoryEmulator. - If the issue persists, file an issue — the handler may need updating for new SDK internals.
- Review the Known Limitations page for documented behavioural differences.
- Check the API Reference for method signatures and available options.
- Consult Choosing Your Approach to ensure you're using the right approach for your scenario.
- File an issue on the GitHub repository with a minimal repro.
Getting Started
Integration & Dependency Injection
Data Management
Reference
Help