{"record":{"id":"b50bbb0573de3922","repo":"dotnet/efcore","slug":"the-type-giventype-cannot-be-mapped-as-a-dicti","errorCode":null,"errorMessage":"The type '{givenType}' cannot be mapped as a dictionary because it does not implement '{dictionaryType}'.","messagePattern":"The type '(.+?)' cannot be mapped as a dictionary because it does not implement '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/ChangeTracking/Internal/StringDictionaryComparer.cs","lineNumber":128,"sourceCode":"        {\n            if (aDictionary.Count != bDictionary.Count)\n            {\n                return false;\n            }\n\n            foreach (var pair in aDictionary)\n            {\n                if (!bDictionary.TryGetValue(pair.Key, out var bValue)\n                    || !elementCompare(pair.Value, bValue))\n                {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        throw new InvalidOperationException(\n            CosmosStrings.BadDictionaryType(\n                (a is IDictionary<string, TElement?> ? b : a).GetType().ShortDisplayName(),\n                typeof(IDictionary<,>).MakeGenericType(typeof(string), typeof(TElement)).ShortDisplayName()));\n    }\n\n    private static int GetHashCode(IEnumerable source, Func<TElement?, int> elementGetHashCode)\n    {\n        if (source is not IReadOnlyDictionary<string, TElement?> sourceDictionary)\n        {\n            throw new InvalidOperationException(\n                CosmosStrings.BadDictionaryType(\n                    source.GetType().ShortDisplayName(),\n                    typeof(IList<>).MakeGenericType(typeof(TElement)).ShortDisplayName()));\n        }\n\n        var hash = new HashCode();\n\n        foreach (var pair in sourceDictionary)","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Cosmos/ChangeTracking/Internal/StringDictionaryComparer.cs#L110-L146","documentation":"The StringDictionaryComparer<TDictionary, TElement>.Compare method throws when neither 'a' nor 'b' implements IReadOnlyDictionary<string, TElement?>. This is an internal change-tracking comparer used by the Cosmos provider for properties mapped as string-keyed dictionaries. The error indicates the runtime type assigned to a dictionary-mapped property does not satisfy the required generic dictionary interface.","triggerScenarios":"A Cosmos entity property is mapped as a dictionary (e.g., Dictionary<string, int>), but at runtime the actual value is a type that does not implement IReadOnlyDictionary<string, TElement?> — for example a non-generic IDictionary, a JObject, or a custom collection that lacks the IReadOnlyDictionary<string, TElement> implementation. The Compare method is called during change tracking when EF compares the snapshot value to the current value.","commonSituations":"Deserializing JSON into a non-generic or weakly-typed container (e.g., Newtonsoft JObject, System.Text.Json JsonElement) that is assigned to a dictionary-mapped property; using a custom collection type that implements IDictionary but not IReadOnlyDictionary<string, TElement>; a model where TElement type inference mismatches the runtime element type.","solutions":["Ensure the runtime type of dictionary-mapped properties implements IReadOnlyDictionary<string, TElement> (Dictionary<string, T> satisfies this).","If deserializing JSON, map into Dictionary<string, TElement> rather than a non-generic or dynamic type.","Check that TElement in the model matches the actual element type stored at runtime."],"exampleFix":"// before — property type is non-generic IDictionary\npublic IDictionary Tags { get; set; } = new Hashtable();\n\n// after — property type implements IReadOnlyDictionary<string, T>\npublic Dictionary<string, string> Tags { get; set; } = new();","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Ensure dictionary-mapped properties implement IReadOnlyDictionary<string, T>\nstatic bool IsValidStringDictionary<TElement>(object? value)\n    => value is null || value is IReadOnlyDictionary<string, TElement>;\n\n// Usage before assigning a value to a Cosmos dictionary-mapped property\nif (!IsValidStringDictionary<string>(entity.Tags))\n{\n    throw new InvalidOperationException(\"Tags must be a Dictionary<string, string>.\");\n}","tryCatchPattern":null,"preventionTips":["Always use Dictionary<string, T> as the property type for Cosmos dictionary-mapped properties.","Ensure custom JSON converters deserialize into Dictionary<string, T>, not JObject or Hashtable.","Avoid assigning non-generic IDictionary or other incompatible collection types to dictionary-mapped properties."],"tags":["ef-core","cosmos","change-tracking","dictionary-mapping","type-mismatch"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}