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

  1. Fix or remove the unknown property from the JSON
  2. Regenerate the C# code so descriptors match the producer's schema version
  3. Align JSON naming with the descriptor (JsonParser matches json_name and original proto name; set json_name options if needed)
  4. 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

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


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)