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

  1. Inspect the stored JSON document (Azure portal / Data Explorer) and correct the value to be a JSON object.
  2. Align the CLR model with the stored shape: if the document stores an array, change the CLR type to a collection, not a Dictionary.
  3. Run a migration to rewrite malformed documents into the expected object shape.
  4. 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

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

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/7247eede7ec9f0fe. Report an issue: GitHub.