XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Any message with no @type

Error message

Any message with no @type

What it means

MergeAny buffers tokens while scanning for an "@type" property at the Any's own object depth. If the object closes (tokenizer.ObjectDepth drops below the recorded depth) before any @type key is found, the Any has no type URL, making the packed message unresolvable, so this InvalidProtocolBufferException is thrown.

Solutions

  1. Include "@type": "type.googleapis.com/<fully.qualified.TypeName>" as a property of the Any JSON object.
  2. Check sanitization/projection code that may strip the @type key before the payload reaches the parser.
  3. Ensure @type is inside the Any's own object, not an enclosing or nested object.
  4. Catch InvalidProtocolBufferException around Parse and reject payloads whose Any fields lack a type URL at ingress validation time.

Example fix

// before: missing @type
{"detail": {"id": 42}}

// after
{"detail": {"@type": "type.googleapis.com/foo.Bar", "id": 42}}
Defensive patterns

Strategy: validation

Validate before calling

// @type must exist and be a string before parsing
function hasTypeUrl(obj) {
  return obj != null && typeof obj === 'object' && typeof obj['@type'] === 'string' && obj['@type'].length > 0;
}

Type guard

function hasAtType(v) { return v !== null && typeof v === 'object' && typeof v['@type'] === 'string'; }

Try / catch

try { var msg = JsonParser.Default.Parse<T>(json); }
catch (InvalidProtocolBufferException ex) when (ex.Message == "Any message with no @type") { /* reject: Any lacks type URL */ }

Prevention

When it happens

Trigger: Parsing an Any field whose JSON object lacks an "@type" property entirely, e.g. {"detail": {"id": 42}}; or the @type key appears at a shallower depth than the Any's own object (misplaced key in a nested structure).

Common situations: Serializers that emit only the inner message fields for Any without @type; hand-written payloads where @type was renamed (e.g. "type" or "typeUrl") or dropped during field filtering; JSON schema validators that strip unknown @-prefixed keys.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

            var token = tokenizer.Next();
            if (token.Type != JsonToken.TokenType.StartObject)
            {
                throw new InvalidProtocolBufferException("Expected object value for Any");
            }
            int typeUrlObjectDepth = tokenizer.ObjectDepth;

            // The check for the property depth protects us from nested Any values which occur before the type URL
            // for *this* Any.
            while (token.Type != JsonToken.TokenType.Name ||
                token.StringValue != JsonFormatter.AnyTypeUrlField ||
                tokenizer.ObjectDepth != typeUrlObjectDepth)
            {
                tokens.Add(token);
                token = tokenizer.Next();

                if (tokenizer.ObjectDepth < typeUrlObjectDepth)
                {
                    throw new InvalidProtocolBufferException("Any message with no @type");
                }
            }

            // Don't add the @type property or its value to the recorded token list
            token = tokenizer.Next();
            if (token.Type != JsonToken.TokenType.StringValue)
            {
                throw new InvalidProtocolBufferException("Expected string value for Any.@type");
            }
            string typeUrl = token.StringValue;
            string typeName = Any.GetTypeName(typeUrl);

            MessageDescriptor descriptor = settings.TypeRegistry.Find(typeName);
            if (descriptor == null)
            {
                throw new InvalidOperationException("Type registry has no descriptor for type name '" + typeName + "'");
            }

View on GitHub (pinned to 016f98412e)