XINCGer/Unity3DTraining · error · InvalidOperationException

Unexpected token type

Error message

Unexpected token type 

What it means

Inside a message object, JsonParser.Merge expects alternating name/value tokens; after a value, the next token must be a field name or end-object. Any other token type indicates malformed JSON structure, so it throws InvalidOperationException (a parser invariant violation rather than a data error).

Solutions

  1. Validate the JSON with a standard parser (JsonDocument.Parse / JsonConvert) before feeding it to JsonParser to get a clearer error
  2. Fix the JSON producer so every object value is preceded by a member name
  3. Ensure one tokenizer per Merge call; do not interleave Next/PushBack incorrectly
  4. If parsing untrusted input, catch InvalidOperationException/InvalidProtocolBufferException and return a 4xx-style parse failure

Example fix

// before
string json = "{ 'a': 1, 2 }"; // missing member name
// after
string json = "{ 'a': 1, 'b': 2 }";
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate JSON structure with the platform parser
using var doc = System.Text.Json.JsonDocument.Parse(json); // throws clearer errors on malformed JSON

Try / catch

try { return parser.Parse<T>(json); } catch (InvalidOperationException ex) when (ex.Message.StartsWith("Unexpected token type")) { log.Error("Malformed JSON structure fed to protobuf parser", ex); throw new BadRequestException("Malformed JSON", ex); }

Prevention

When it happens

Trigger: Feeding structurally invalid JSON to JsonParser where an object member name is missing — e.g. two consecutive values without a key, an unterminated object, or a tokenizer/reader mismatch such as reusing a tokenizer across messages.

Common situations: Hand-built or template-generated JSON with missing keys; string concatenation producing malformed JSON; parser bugs or misuse of PushBack/tokenizer API in custom code paths.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12). Data as JSON: /api/errors/a9e78acb93deae24. Report an issue: GitHub.

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs:185

            {
                throw new InvalidProtocolBufferException("Expected an object");
            }
            var descriptor = message.Descriptor;
            var jsonFieldMap = descriptor.Fields.ByJsonName();
            // All the oneof fields we've already accounted for - we can only see each of them once.
            // The set is created lazily to avoid the overhead of creating a set for every message
            // we parsed, when oneofs are relatively rare.
            HashSet<OneofDescriptor> seenOneofs = null;
            while (true)
            {
                token = tokenizer.Next();
                if (token.Type == JsonToken.TokenType.EndObject)
                {
                    return;
                }
                if (token.Type != JsonToken.TokenType.Name)
                {
                    throw new InvalidOperationException("Unexpected token type " + token.Type);
                }
                string name = token.StringValue;
                FieldDescriptor field;
                if (jsonFieldMap.TryGetValue(name, out field))
                {
                    if (field.ContainingOneof != null)
                    {
                        if (seenOneofs == null)
                        {
                            seenOneofs = new HashSet<OneofDescriptor>();
                        }
                        if (!seenOneofs.Add(field.ContainingOneof))
                        {
                            throw new InvalidProtocolBufferException("Multiple values specified for oneof " + field.ContainingOneof.Name);
                        }
                    }
                    MergeField(message, field, tokenizer);
                }

View on GitHub (pinned to 016f98412e)