XINCGer/Unity3DTraining · error · InvalidProtocolBufferException
Unknown field:
Error message
Unknown field:
What it means
By default JsonParser rejects JSON object keys that do not match any field in the message descriptor (neither JSON name nor original name), throwing InvalidProtocolBufferException with the unknown field's name. Proto JSON parsers are strict unless configured otherwise.
Solutions
- Fix or remove the unknown property from the JSON
- Regenerate the C# code so descriptors match the producer's schema version
- Align JSON naming with the descriptor (JsonParser matches json_name and original proto name; set json_name options if needed)
- Add the missing field to the .proto if the producer legitimately sends it
Example fix
// before
{ "userName": "bob" } // proto field is 'username'
// after
{ "username": "bob" } Defensive patterns
Strategy: try-catch
Validate before calling
// Check all JSON keys exist in the schema before parsing (pseudo-validation of names) bool KnownField(string jsonKey) => descriptor.Fields.ByJsonName().ContainsKey(jsonKey) || descriptor.Fields.ByName().ContainsKey(jsonKey);
Try / catch
try { return parser.Parse<T>(json); } catch (InvalidProtocolBufferException ex) when (ex.Message.StartsWith("Unknown field:")) { log.Error($"JSON contains a field not in {typeof(T).Name}: {ex.Message}"); throw new BadRequestException(ex.Message, ex); } Prevention
- Keep generated code in sync with the producer's .proto version
- Preserve json_name when renaming proto fields
- Log and monitor unknown-field errors to catch schema drift early
When it happens
Trigger: Parsing JSON containing a property whose name matches no field — typos, camelCase/snake_case mismatches when the field was renamed, fields added in a newer schema version but parsed with older generated code, or leftover fields removed from the .proto.
Common situations: Schema drift between producer and consumer; renaming a proto field without preserving json_name; third-party services adding extra properties; forwarding client JSON payloads verbatim into a stricter message type.
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
- Repeated field value was not an array. Token type:
- Expected end of JSON after object
- Expected an object
- Unexpected token type
- Multiple values specified for oneof
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/dd4dacc1f9a76dab.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs:209
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);
}
else
{
// TODO: Is this what we want to do? If not, we'll need to skip the value,
// which may be an object or array. (We might want to put code in the tokenizer
// to do that.)
throw new InvalidProtocolBufferException("Unknown field: " + name);
}
}
}
private void MergeField(IMessage message, FieldDescriptor field, JsonTokenizer tokenizer)
{
var token = tokenizer.Next();
if (token.Type == JsonToken.TokenType.Null)
{
// Clear the field if we see a null token, unless it's for a singular field of type
// google.protobuf.Value.
// Note: different from Java API, which just ignores it.
// TODO: Bring it more in line? Discuss...
if (field.IsMap || field.IsRepeated || !IsGoogleProtobufValueField(field))
{
field.Accessor.Clear(message);
return;
}View on GitHub (pinned to 016f98412e)