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

  1. Point TypeName at the actual enum, or set Type = TYPE_MESSAGE if a message is intended, then regenerate.
  2. Regenerate all descriptor sets from the .proto sources to keep Type and TypeName consistent.
  3. 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

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


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)