XINCGer/Unity3DTraining · error · DescriptorValidationException
"TypeName" is not an enum type.
Error message
"TypeName" is not an enum type.
What it means
During CrossLink, if the field's resolved type is FieldType.Enum, the type_name must resolve to an EnumDescriptor. If the pool lookup returned a MessageDescriptor or other symbol, the field claims to be an enum but names a message, so DescriptorValidationException is thrown.
Solutions
- Point TypeName at the actual enum, or set Type = TYPE_MESSAGE if a message is intended, then regenerate.
- Regenerate all descriptor sets from the .proto sources to keep Type and TypeName consistent.
- Before CrossLink, resolve TypeName and assert the symbol kind matches the declared field type.
Example fix
// before (proto) optional MyMessage status = 1; // Type still TYPE_ENUM // after optional MyMessage status = 1; // with Type = TYPE_MESSAGE
Defensive patterns
Strategy: validation
Validate before calling
if (field.Proto.Type == FieldDescriptorProto.Types.Type.Enum)
{
var sym = pool.FindSymbol(field.Proto.TypeName);
if (!(sym is EnumDescriptor)) throw new InvalidDataException(field.Proto.TypeName + " is not an enum");
} Type guard
bool IsEnumField(FieldDescriptorProto f, DescriptorPool pool) =>
f.Type != FieldDescriptorProto.Types.Type.Enum || pool.FindSymbol(f.TypeName) is EnumDescriptor; Try / catch
try { descriptor = FileDescriptor.BuildFromByteStrings(data); }
catch (DescriptorValidationException ex) when (ex.Message.Contains("is not an enum type"))
{ log.LogError(ex, "Type/TypeName mismatch on enum field"); } Prevention
- Keep Type = TYPE_ENUM only for fields naming actual enums.
- Regenerate descriptors whenever a shared .proto changes a type's kind.
- Validate Type against resolved symbol kind at descriptor import time.
When it happens
Trigger: A field with Type = TYPE_ENUM whose TypeName resolves to a message type — usually because the declared Type was edited (manually or by a tool) without updating TypeName, or the .proto changed 'enum X' to 'message X' and dependents were not regenerated.
Common situations: Converting an enum to a message in a shared .proto while generated descriptors elsewhere still say TYPE_ENUM; hand-built descriptors with swapped Type/TypeName pairs.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- "TypeName" is not a message type.
- Field with primitive type has type_name.
- Expected an object
- Unsupported JSON token type
- Unsupported conversion from JSON number for field type
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/6162d9ec86799c37.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/Reflection/FieldDescriptor.cs:338
if (fieldType == FieldType.Message)
{
if (!(typeDescriptor is MessageDescriptor))
{
throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a message type.");
}
messageType = (MessageDescriptor)typeDescriptor;
if (Proto.DefaultValue != "")
{
throw new DescriptorValidationException(this, "Messages can't have default values.");
}
}
else if (fieldType == FieldType.Enum)
{
if (!(typeDescriptor is EnumDescriptor))
{
throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not an enum type.");
}
enumType = (EnumDescriptor)typeDescriptor;
}
else
{
throw new DescriptorValidationException(this, "Field with primitive type has type_name.");
}
}
else
{
if (fieldType == FieldType.Message || fieldType == FieldType.Enum)
{
throw new DescriptorValidationException(this, "Field with message or enum type missing type_name.");
}
}
// Note: no attempt to perform any default value parsing
View on GitHub (pinned to 016f98412e)