XINCGer/Unity3DTraining · error · InvalidProtocolBufferException
Expected object value for Any
Error message
Expected object value for Any
What it means
An Any value's canonical JSON is an object containing at minimum an "@type" key (plus the packed inner message fields). MergeAny reads the first token and, if it is not StartObject, throws this InvalidProtocolBufferException before it can scan for @type.
Solutions
- Emit Any as a JSON object: {"@type": "type.googleapis.com/pkg.Msg", ...inner fields}.
- If you have a raw inner message JSON, wrap it: merge the type URL key into the inner object before parsing.
- If a plain string was intended, change the schema field type from Any to string.
- Catch InvalidProtocolBufferException and inspect the payload to confirm the Any field's JSON shape.
Example fix
// before: Any as a bare string
{"detail": "type.googleapis.com/foo.Bar"}
// after
{"detail": {"@type": "type.googleapis.com/foo.Bar", "id": 42}} Defensive patterns
Strategy: validation
Validate before calling
// Any fields must be objects containing @type
function validateAnyField(payload, name) {
const v = payload[name];
if (v !== undefined && (typeof v !== 'object' || v === null || Array.isArray(v))) {
throw new Error(`${name} (google.protobuf.Any) must be a JSON object with @type`);
}
} Type guard
function isAnyLike(v) { return v !== null && typeof v === 'object' && !Array.isArray(v) && typeof v['@type'] === 'string'; } Try / catch
try { var msg = JsonParser.Default.Parse<T>(json); }
catch (InvalidProtocolBufferException ex) when (ex.Message == "Expected object value for Any") { /* reject payload: Any must be an object */ } Prevention
- Always wrap Any values as {"@type": url, ...fields}
- Never serialize Any as just the type URL string
- Add ingress validation for Any-typed fields
When it happens
Trigger: Calling JsonParser.Parse where a google.protobuf.Any field receives a JSON string (e.g. the bare type URL), a number, an array, or null instead of an object, e.g. {"detail": "type.googleapis.com/foo.Bar"}.
Common situations: APIs that serialize Any as just the type URL or the inner message without the object wrapper; clients that stringify the Any value; confusion between Any and StringValue/bytes fields.
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
- Expected object value for Struct
- Any message with no @type
- Expected string value for Any.@type
- Type registry has no descriptor for type name '
- Expected end of JSON after object
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/1b950d0fb5354dac.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs:491
{
throw new InvalidProtocolBufferException("Expected object value for Struct");
}
tokenizer.PushBack(token);
var field = message.Descriptor.Fields[Struct.FieldsFieldNumber];
MergeMapField(message, field, tokenizer);
}
private void MergeAny(IMessage message, JsonTokenizer tokenizer)
{
// Record the token stream until we see the @type property. At that point, we can take the value, consult
// the type registry for the relevant message, and replay the stream, omitting the @type property.
var tokens = new List<JsonToken>();
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");
}
}
View on GitHub (pinned to 016f98412e)