XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Invalid enum value:

Error message

Invalid enum value: 

What it means

Google.Protobuf's JsonParser throws InvalidProtocolBufferException when converting JSON to a protobuf message. In ParseSingleStringValue, a JSON string field whose FieldType is Enum is resolved via the enum descriptor's FindValueByName; if the string is not a declared enum value name, this error is thrown. The protobuf JSON spec requires enum values in JSON to be the value name (e.g. "VALUE_A"), not an alias or arbitrary text.

Solutions

  1. Use the exact enum value name declared in the .proto file for the field's enum type
  2. Check field.EnumType.FullName's declared values (e.g. dump the EnumDescriptor values) and match the JSON string to one of them
  3. If you must send a number, use a JSON number instead of a string so the parser takes the numeric path
  4. Regenerate the C# protobuf classes from the current .proto so descriptors contain the value names you send
  5. Add the missing value or an allow_alias entry to the proto enum if the name is legitimately new

Example fix

// before
var msg = MessageParser.Parse('{"state": "2"}'); // throws: no enum value named "2"
// after
var msg = MessageParser.Parse('{"state": "STATE_INACTIVE"}'); // matches declared proto value
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidEnumJson(string json, MessageDescriptor d) {
    // For each enum field, check the string against EnumType.FindValueByName before parsing.
    foreach (var f in d.Fields.InFieldNumberOrder())
        if (f.FieldType == FieldType.Enum && json.Contains("\"" + f.JsonName + "\": \""))
            if (f.EnumType.FindValueByName(ExtractEnumString(json, f.JsonName)) == null) return false;
    return true;
}

Type guard

bool IsKnownEnumValue(string text, EnumDescriptor e) => e.FindValueByName(text) != null;

Try / catch

try { return JsonParser.Default.Parse<T>(json); }
catch (InvalidProtocolBufferException ex) when (ex.Message.StartsWith("Invalid enum value")) {
    logger.LogWarning(ex, "Unknown enum name in JSON");
    return null; // or repair/migrate the payload
}

Prevention

When it happens

Trigger: Calling JsonParser.Parse<T>(json) (directly or via JsonFormatter/Parse on a message containing enum fields) where a string value for an enum-typed field does not exactly match a registered enum value name, e.g. sending "ACTIVE" when the proto declares only STATUS_ACTIVE, or sending a numeric enum as a string like "2" when no alias named "2" exists.

Common situations: Older/newer .proto versions between client and server so the enum name was renamed or removed; hand-written JSON using numeric or ad-hoc strings for enums; code generators out of sync after regenerating C# stubs; typos or case mismatches (JSON enum names are case-sensitive here).

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

                case FieldType.SInt64:
                case FieldType.SFixed64:
                    return ParseNumericString<long>(text, long.Parse);
                case FieldType.UInt64:
                case FieldType.Fixed64:
                    return ParseNumericString<ulong>(text, ulong.Parse);
                case FieldType.Double:
                    double d = ParseNumericString<double>(text, double.Parse);
                    ValidateInfinityAndNan(text, double.IsPositiveInfinity(d), double.IsNegativeInfinity(d), double.IsNaN(d));
                    return d;
                case FieldType.Float:
                    float f = ParseNumericString<float>(text, float.Parse);
                    ValidateInfinityAndNan(text, float.IsPositiveInfinity(f), float.IsNegativeInfinity(f), float.IsNaN(f));
                    return f;
                case FieldType.Enum:
                    var enumValue = field.EnumType.FindValueByName(text);
                    if (enumValue == null)
                    {
                        throw new InvalidProtocolBufferException("Invalid enum value: " + text + " for enum type: " + field.EnumType.FullName);
                    }
                    // Just return it as an int, and let the CLR convert it.
                    return enumValue.Number;
                default:
                    throw new InvalidProtocolBufferException("Unsupported conversion from JSON string for field type " + field.FieldType);
            }
        }

        /// <summary>
        /// Creates a new instance of the message type for the given field.
        /// </summary>
        private static IMessage NewMessageForField(FieldDescriptor field)
        {
            return field.MessageType.Parser.CreateTemplate();
        }

        private static T ParseNumericString<T>(string text, Func<string, NumberStyles, IFormatProvider, T> parser)
        {

View on GitHub (pinned to 016f98412e)