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
- Send exactly one member of the oneof in the JSON; remove the conflicting key
- Check the .proto definition to see which fields share the oneof and update the client
- If migrating, keep old fields out of oneofs or version the message schema
- 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
- Document oneof semantics for API clients; send exactly one member
- When moving fields into a oneof, version the API and inform senders
- Reject conflicting keys at your API gateway before parsing
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
- Repeated field elements cannot be null
- Expected end of JSON after object
- Expected an object
- Unexpected token type
- Unknown field:
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)