XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Map values must not be null

Error message

Map values must not be null

What it means

Protobuf map entries cannot have null values: every map entry stores a concrete key and value. When parsing a map field's JSON, if the value token is JSON null (even for message-typed values, where null could conceptually mean an empty message), MergeMapField rejects it with this InvalidProtocolBufferException.

Solutions

  1. Remove null entries from the map JSON before parsing — an entry whose value is null should either be omitted entirely or given a default/empty value.
  2. Replace null with the default value for the value type (empty string, 0, empty message object like {}).
  3. Sanitize dictionaries before serialization: filter out entries with null values before emitting JSON.
  4. If nulls are meaningful, change the schema to wrap the value in a message with an optional field (e.g. google.protobuf.Value or a wrapper message).

Example fix

// before
{"myMap": {"a": null, "b": 2}}

// after: omit or default the null entry
{"myMap": {"b": 2}}   // or {"myMap": {"a": "", "b": 2}}
Defensive patterns

Strategy: validation

Validate before calling

// Strip null-valued map entries before parsing
function cleanMap(m) {
  return Object.fromEntries(Object.entries(m).filter(([, v]) => v !== null));
}
if (payload.myMap) payload.myMap = cleanMap(payload.myMap);

Try / catch

try { var msg = JsonParser.Default.Parse<T>(json); }
catch (InvalidProtocolBufferException ex) when (ex.Message == "Map values must not be null") { /* sanitize payload and retry once */ }

Prevention

When it happens

Trigger: Calling JsonParser.Parse with JSON like {"myMap": {"key1": null}} — a null as the value of any map entry, regardless of the value type.

Common situations: JSON serialized from dictionaries that contained null values (common in C#/Java maps with nullable reference values); frontend code emitting null for absent values; interop with systems that allow null map values (e.g. OpenAPI-style maps) before feeding protobuf JSON parsing.

Related errors


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

Appendix: source

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

            var valueField = type.FindFieldByNumber(2);
            if (keyField == null || valueField == null)
            {
                throw new InvalidProtocolBufferException("Invalid map field: " + field.FullName);
            }
            IDictionary dictionary = (IDictionary)field.Accessor.GetValue(message);

            while (true)
            {
                token = tokenizer.Next();
                if (token.Type == JsonToken.TokenType.EndObject)
                {
                    return;
                }
                object key = ParseMapKey(keyField, token.StringValue);
                object value = ParseSingleValue(valueField, tokenizer);
                if (value == null)
                {
                    throw new InvalidProtocolBufferException("Map values must not be null");
                }
                dictionary[key] = value;
            }
        }

        private static bool IsGoogleProtobufValueField(FieldDescriptor field)
        {
            return field.FieldType == FieldType.Message &&
                field.MessageType.FullName == Value.Descriptor.FullName;
        }

        private object ParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer)
        {
            var token = tokenizer.Next();
            if (token.Type == JsonToken.TokenType.Null)
            {
                // TODO: In order to support dynamic messages, we should really build this up
                // dynamically.

View on GitHub (pinned to 016f98412e)