XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Multiple values specified for oneof

Error message

Multiple values specified for oneof 

What it means

Proto3 oneof fields may have at most one member set. When JSON contains values for two or more members of the same oneof, JsonParser.Merge detects the second assignment via its seenOneofs set and throws InvalidProtocolBufferException naming the oneof.

Solutions

  1. Send exactly one member of the oneof in the JSON; remove the conflicting key
  2. Check the .proto definition to see which fields share the oneof and update the client
  3. If migrating, keep old fields out of oneofs or version the message schema
  4. Pre-validate the JSON (count oneof member keys) before calling Parse when accepting external input

Example fix

// before
{ "amountCents": 100, "amountEuros": 90 }   // both in oneof 'amount'
// after
{ "amountCents": 100 }
Defensive patterns

Strategy: validation

Validate before calling

// Reject JSON objects that set more than one member of any oneof (adjust names per schema)
static bool SetsMultipleOneofMembers(System.Text.Json.JsonElement obj, string[] oneofMembers) => oneofMembers.Count(m => obj.TryGetProperty(m, out _)) > 1;

Try / catch

try { return parser.Parse<T>(json); } catch (InvalidProtocolBufferException ex) when (ex.Message.StartsWith("Multiple values specified for oneof")) { log.Error("JSON sets multiple members of a oneof"); throw new BadRequestException(ex.Message, ex); }

Prevention

When it happens

Trigger: Parsing JSON like {"fieldA": 1, "fieldB": 2} where fieldA and fieldB belong to the same oneof; merging two JSON patches that each set a different member of the same oneof; schema evolution where a field moved into a oneof and older clients still send the old sibling field.

Common situations: Clients unaware a field was moved into a oneof after a proto refactor; JSON merge/patch operations combining documents; manually written JSON setting several variants at once.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

                    return;
                }
                if (token.Type != JsonToken.TokenType.Name)
                {
                    throw new InvalidOperationException("Unexpected token type " + token.Type);
                }
                string name = token.StringValue;
                FieldDescriptor field;
                if (jsonFieldMap.TryGetValue(name, out field))
                {
                    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)

View on GitHub (pinned to 016f98412e)