XINCGer/Unity3DTraining · error · DescriptorValidationException
"TypeName" is not a type.
Error message
"TypeName" is not a type.
What it means
During CrossLink, a field that uses type_name (rather than an inline type) must resolve, via the descriptor pool, to either a MessageDescriptor or an EnumDescriptor. If the resolved symbol is neither, the field's TypeName points at something that exists but is not a type (e.g. a service or another field), and DescriptorValidationException is thrown.
Solutions
- Fix Proto.TypeName to the correct fully-qualified message or enum name and regenerate/rebuild the descriptor.
- Verify with DescriptorPool.LookupSymbol / FindName that the name resolves to a MessageDescriptor or EnumDescriptor before building.
- Regenerate descriptors from the .proto source with protoc instead of editing serialized descriptor bytes.
Example fix
// before typeName = "MyApp.Services.MyService" // resolves to a service, not a type // after typeName = "MyApp.Messages.MyMessage"
Defensive patterns
Strategy: validation
Validate before calling
var sym = pool.LookupSymbol(field.Proto.TypeName, field);
if (!(sym is MessageDescriptor) && !(sym is EnumDescriptor))
throw new InvalidDataException(field.Proto.TypeName + " is not a message or enum type"); Type guard
bool IsNamedType(string typeName, DescriptorPool pool, out object sym)
{ sym = pool.FindSymbol(typeName); return sym is MessageDescriptor || sym is EnumDescriptor; } Try / catch
try { descriptor = FileDescriptor.BuildFromByteStrings(data); }
catch (DescriptorValidationException ex)
{ log.LogError(ex, "type_name does not resolve to a type: " + ex.Message); } Prevention
- Use fully-qualified type names exactly as protoc generates them.
- Regenerate descriptors after renaming or merging types in .proto files.
- Validate type_name resolution before feeding descriptors to the builder.
When it happens
Trigger: A FieldDescriptorProto whose Type is TYPE_MESSAGE/TYPE_ENUM but whose TypeName resolves to a non-type symbol in the pool — e.g. TypeName pointing at a service, method, or field; misspelled or wrongly-scoped fully-qualified type names in hand-built protos.
Common situations: Hand-assembling descriptors with wrong fully-qualified names; renaming/merging protos so a type_name now collides with a non-type symbol; stale generated descriptor sets after refactors.
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
- FieldDescriptorProto.oneof_index is out of range for type
- Invalid type specified
- "TypeName" is not a message type.
- Messages can't have default values.
- "TypeName" is not an enum type.
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/b03efeb85cfd053c.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/Reflection/FieldDescriptor.cs:317
if (Proto.TypeName != "")
{
IDescriptor typeDescriptor =
File.DescriptorPool.LookupSymbol(Proto.TypeName, this);
if (Proto.Type != 0)
{
// Choose field type based on symbol.
if (typeDescriptor is MessageDescriptor)
{
fieldType = FieldType.Message;
}
else if (typeDescriptor is EnumDescriptor)
{
fieldType = FieldType.Enum;
}
else
{
throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a type.");
}
}
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)
{View on GitHub (pinned to 016f98412e)