dotnet/efcore · error · InvalidOperationException

Invalid token type: ' '.

Error message

Invalid token type: '{tokenType}'.

What it means

The shaper's client method scans the Cosmos response stream for the 'Documents' array. After locating the property it expects JsonTokenType.StartArray; any other token type throws InvalidOperationException CoreStrings.JsonReaderInvalidTokenType with the offending token. A second throw at the end of the loop fires if 'Documents' is never found.

Solutions

  1. Capture the raw response (Fiddler/emulator logs) and confirm the 'Documents' array is present and well-formed.
  2. Check for upstream failures (429/503) that return a status body without 'Documents'.
  3. Regenerate continuation tokens; do not reuse tokens across schema or partition key changes.
Defensive patterns

Strategy: retry

Try / catch

try
{
    await foreach (var item in query.WithCancellation(ct)) { /* ... */ }
}
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Invalid token type"))
{
    // log raw response via Cosmos diagnostics; re-issue or surface a domain error
    logger.LogError(ex, "Cosmos response shape unexpected");
    throw;
}

Prevention

When it happens

Trigger: The Cosmos response payload does not contain a 'Documents' array where the shaper expects it — caused by an unexpected response shape (error payload, proxy rewriting the body, malformed continuation).

Common situations: A gateway/proxy returning an error JSON instead of the documents envelope, a Cosmos emulator bug producing a non-standard body, or a corrupted continuation token resuming mid-payload.

Understand the failure class

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/8476bf4505539bd4. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs:36

        private static readonly byte EndArrayByte = Encoding.UTF8.GetBytes("]")[0];
        private static readonly byte NextItemByte = Encoding.UTF8.GetBytes(",")[0];

        public static ReadOnlyMemory<byte> ExtractDocuments(ReadOnlyMemory<byte> data)
        {
            var documentsReader = new Utf8JsonReader(data.Span);

            documentsReader.Read();
            Debug.Assert(documentsReader.TokenType == JsonTokenType.StartObject);

            documentsReader.Read();
            while (documentsReader.TokenType == JsonTokenType.PropertyName)
            {
                if (documentsReader.ValueTextEquals("Documents"))
                {
                    documentsReader.Read();
                    var token = documentsReader.TokenType;
                    return token != JsonTokenType.StartArray
                        ? throw new InvalidOperationException(CoreStrings.JsonReaderInvalidTokenType(token))
                        : data[(int)documentsReader.BytesConsumed..];
                }

                documentsReader.Skip();
                documentsReader.Read();
            }

            throw new InvalidOperationException(CoreStrings.JsonReaderInvalidTokenType(documentsReader.TokenType));
        }

        public static bool TryMaterializeNextJsonCollectionItem<T>(
            QueryContext queryContext,
            ReadOnlyMemory<byte> data,
            Shaper<T> shaper,
            int ordinal,
            out int bytesConsumed,
            [NotNullWhen(true)] out T? result)
        {

View on GitHub (pinned to 3a2006ef56)