dotnet/efcore · error · InvalidOperationException
Invalid token type: '{tokenType}'.
Error message
Invalid token type: '{tokenType}'. What it means
Thrown by CosmosJsonStringKeyedDictionaryReaderWriter<TElement>.FromJsonTyped when the JSON reader is not positioned on a StartObject token while deserializing a Dictionary<string,TElement> from a Cosmos document. Cosmos stores dictionaries as JSON objects; if the stored JSON value is an array, primitive, or the reader is mispositioned, the token type is rejected (CoreStrings.JsonReaderInvalidTokenType).
Source
Thrown at src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs:330
public sealed class CosmosJsonStringKeyedDictionaryReaderWriter<TElement>(JsonValueReaderWriter elementReaderWriter)
: JsonValueReaderWriter<IEnumerable<KeyValuePair<string, TElement>>>, ICompositeJsonValueReaderWriter
#pragma warning restore EF1001
{
private readonly JsonValueReaderWriter<TElement> _elementReaderWriter = (JsonValueReaderWriter<TElement>)elementReaderWriter;
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override IEnumerable<KeyValuePair<string, TElement>> FromJsonTyped(
ref Utf8JsonReaderManager manager,
object? existingObject = null)
{
if (manager.CurrentReader.TokenType != JsonTokenType.StartObject)
{
throw new InvalidOperationException(CoreStrings.JsonReaderInvalidTokenType(manager.CurrentReader.TokenType));
}
var dictionary = new Dictionary<string, TElement>();
while (true)
{
switch (manager.MoveNext())
{
case JsonTokenType.PropertyName:
var key = manager.CurrentReader.GetString()!;
manager.MoveNext();
dictionary.Add(key, _elementReaderWriter.FromJsonTyped(ref manager));
break;
case JsonTokenType.EndObject:
return dictionary;
default:
throw new InvalidOperationException(CoreStrings.JsonReaderInvalidTokenType(manager.CurrentReader.TokenType));
}
}View on GitHub (pinned to dbf9771522)
Solutions
- Inspect the stored JSON document (Azure portal / Data Explorer) and correct the value to be a JSON object.
- Align the CLR model with the stored shape: if the document stores an array, change the CLR type to a collection, not a Dictionary.
- Run a migration to rewrite malformed documents into the expected object shape.
- Ensure all writers use EF Core SaveChanges (consistent serialization) rather than external tools that produce different shapes.
Example fix
// before: document stored as
// { "Tags": [ {"k":"a","v":1}, {"k":"b","v":2} ] }
// with model: public Dictionary<string,int> Tags { get; set; }
// -> throws JsonReaderInvalidTokenType (array, not object)
// after: store as object
// { "Tags": { "a": 1, "b": 2 } }
// or change model to match: public List<KeyValuePair<string,int>> Tags { get; set; } Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the raw JSON shape before mapping
var raw = await container.ReadItemAsync<JToken>(id, new PartitionKey(pk));
if (raw.Resource[propertyName] is JObject) { /* ok: object */ }
else { throw new SchemaException($"{propertyName} must be a JSON object."); } Type guard
bool IsJsonObject(JToken token) => token is JObject; // for System.Text.Json: // bool IsJsonObject(ref Utf8JsonReader r) => r.TokenType == JsonTokenType.StartObject;
Try / catch
try { var entity = await db.Set<MyEntity>().FindAsync(id); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Invalid token type"))
{
// schema mismatch in stored document; surface as a data-integrity error and log the document id
throw new DataIntegrityException($"Document {id} has an unexpected JSON shape for a dictionary property.", ex);
} Prevention
- Inspect stored documents in Data Explorer before relying on a Dictionary mapping.
- Write documents only through EF Core to keep serialization consistent.
- Run a one-time schema validation pass after migrations.
- Pin a single serializer/config for dictionary properties across versions.
When it happens
Trigger: Reading a Cosmos document whose serialized dictionary property is not a JSON object (e.g. it is a JSON array or string); corrupt or hand-edited documents; schema drift where a property changed type between versions; partial/malformed JSON returned from a stored procedure.
Common situations: Documents written by a different serializer or older app version; manual edits in the Azure portal; migration tooling that wrote arrays instead of objects; mismatched model (property declared as Dictionary but document contains an array of pairs).
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Invalid token type: '{tokenType}'.
- The property '{1_entityType}.{0_property}' contains null, bu
- The type '{givenType}' cannot be mapped as a dictionary beca
- The entity type '{entityType}' does not have a property mapp
- The Cosmos database provider does not support transactions.
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/7247eede7ec9f0fe.
Report an issue: GitHub.