XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Expected '

Error message

Expected '

What it means

When the JsonParser parses the body of an Any holding a well-known type (e.g. google.protobuf.Timestamp), it expects the JSON object to contain exactly the property named 'value' (JsonFormatter.AnyWellKnownTypeValueField) after '@type'. Any other property name is rejected with this InvalidProtocolBufferException.

Solutions

  1. Rename the inner property to exactly 'value' (the canonical AnyWellKnownTypeValueField).
  2. If you control the producer, serialize well-known types inside Any per the protobuf JSON spec: {"@type":"...","value":<encoded wkt>}.
  3. Verify JSON casing policy (camelCase) isn't rewriting 'value' to something else.

Example fix

// before
{"@type":"type.googleapis.com/google.protobuf.Duration","val":"5s"}
// after
{"@type":"type.googleapis.com/google.protobuf.Duration","value":"5s"}
Defensive patterns

Strategy: validation

Validate before calling

// Validate Any well-known-type bodies have the canonical 'value' property
var anyObjs = Regex.Matches(json, '"@type"\\s*:\\s*"[^"]+"\\s*,\\s*"([^"]+)"');
foreach (Match m in anyObjs)
    if (m.Groups[1].Value != "value") throw new Exception($"Any body must use 'value', got '{m.Groups[1].Value}'");

Try / catch

try
{
    var msg = parser.Parse<T>(json);
}
catch (InvalidProtocolBufferException ex) when (ex.Message.Contains("property for well-known type Any body"))
{
    // inspect/repair the offending JSON or surface a clear client-side error
}

Prevention

When it happens

Trigger: Parsing an Any body like {"@type":"type.googleapis.com/google.protobuf.Timestamp","value":"..."} where the second property is misspelled (e.g. 'Value', 'val') or in wrong order/casing, so the first token after @type is not a Name token equal to the canonical field name.

Common situations: Hand-crafted or third-party-generated JSON for Any-wrapped well-known types with wrong property casing or naming; serializers that don't follow the canonical Any well-known-type encoding.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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

Appendix: source

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

            }
            var data = body.ToByteString();

            // Now that we have the message data, we can pack it into an Any (the message received as a parameter).
            message.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.SetValue(message, typeUrl);
            message.Descriptor.Fields[Any.ValueFieldNumber].Accessor.SetValue(message, data);
        }

        // Well-known types end up in a property called "value" in the JSON. As there's no longer a @type property
        // in the given JSON token stream, we should *only* have tokens of start-object, name("value"), the value
        // itself, and then end-object.
        private void MergeWellKnownTypeAnyBody(IMessage body, JsonTokenizer tokenizer)
        {
            var token = tokenizer.Next(); // Definitely start-object; checked in previous method
            token = tokenizer.Next();
            // TODO: What about an absent Int32Value, for example?
            if (token.Type != JsonToken.TokenType.Name || token.StringValue != JsonFormatter.AnyWellKnownTypeValueField)
            {
                throw new InvalidProtocolBufferException("Expected '" + JsonFormatter.AnyWellKnownTypeValueField + "' property for well-known type Any body");
            }
            Merge(body, tokenizer);
            token = tokenizer.Next();
            if (token.Type != JsonToken.TokenType.EndObject)
            {
                throw new InvalidProtocolBufferException("Expected end-object token after @type/value for well-known type");
            }
        }

        #region Utility methods which don't depend on the state (or settings) of the parser.
        private static object ParseMapKey(FieldDescriptor field, string keyText)
        {
            switch (field.FieldType)
            {
                case FieldType.Bool:
                    if (keyText == "true")
                    {
                        return true;

View on GitHub (pinned to 016f98412e)