XINCGer/Unity3DTraining · error · ArgumentException

Invalid type specified

Error message

Invalid type specified

What it means

GetFieldTypeFromProtoType maps a FieldDescriptorProto.Type enum value to the public FieldType enum; if it encounters a Type value it does not recognize, it throws ArgumentException("Invalid type specified"). This happens when the descriptor carries an unknown or out-of-range wire enum value (e.g. a newer proto syntax/type added after this plugin was compiled).

Solutions

  1. Upgrade the bundled Google.Protobuf plugin to a version matching (or newer than) the protoc that produced the descriptor.
  2. Regenerate the descriptor with a protoc version compatible with the plugin's known Type values.
  3. Validate the proto.Type value against Enum.IsDefined(typeof(FieldDescriptorProto.Types.Type), value) before constructing descriptors from untrusted input.

Example fix

// before
type = (FieldDescriptorProto.Types.Type)rawInt;
// after
if (Enum.IsDefined(typeof(FieldDescriptorProto.Types.Type), rawInt))
    type = (FieldDescriptorProto.Types.Type)rawInt;
else
    throw new InvalidDataException("Unknown field type " + rawInt);
Defensive patterns

Strategy: validation

Validate before calling

if (!Enum.IsDefined(typeof(FieldDescriptorProto.Types.Type), field.Proto.Type))
    throw new InvalidDataException($"Unknown field type value {(int)field.Proto.Type}");

Type guard

bool IsKnownFieldType(FieldDescriptorProto.Types.Type t) => Enum.IsDefined(typeof(FieldDescriptorProto.Types.Type), t);

Try / catch

try { descriptor = FieldDescriptor.FromProto(proto, parent); }
catch (ArgumentException ex) when (ex.Message == "Invalid type specified")
{ log.LogError("Descriptor uses a field type unknown to this Google.Protobuf version"); }

Prevention

When it happens

Trigger: Constructing a FieldDescriptor whose proto.Type is not one of the FieldDescriptorProto.Types values known to this Google.Protobuf version, typically from a serialized FileDescriptorProto produced by a newer protoc, or by casting an arbitrary int into FieldDescriptorProto.Types.Type.

Common situations: Mixing descriptor files generated by a newer protoc with an old bundled Google.Protobuf plugin; manual int-to-enum casts when building protos dynamically.

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/0b0f1781cecbe42f. Report an issue: GitHub.

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/Reflection/FieldDescriptor.cs:184

                    return FieldType.Group;
                case FieldDescriptorProto.Types.Type.Message:
                    return FieldType.Message;
                case FieldDescriptorProto.Types.Type.Bytes:
                    return FieldType.Bytes;
                case FieldDescriptorProto.Types.Type.Uint32:
                    return FieldType.UInt32;
                case FieldDescriptorProto.Types.Type.Enum:
                    return FieldType.Enum;
                case FieldDescriptorProto.Types.Type.Sfixed32:
                    return FieldType.SFixed32;
                case FieldDescriptorProto.Types.Type.Sfixed64:
                    return FieldType.SFixed64;
                case FieldDescriptorProto.Types.Type.Sint32:
                    return FieldType.SInt32;
                case FieldDescriptorProto.Types.Type.Sint64:
                    return FieldType.SInt64;
                default:
                    throw new ArgumentException("Invalid type specified");
            }
        }

        /// <summary>
        /// Returns <c>true</c> if this field is a repeated field; <c>false</c> otherwise.
        /// </summary>
        public bool IsRepeated
        {
            get
            {
                return Proto.Label == FieldDescriptorProto.Types.Label.Repeated;
            }
        }

        /// <summary>
        /// Returns <c>true</c> if this field is a map field; <c>false</c> otherwise.
        /// </summary>
        public bool IsMap

View on GitHub (pinned to 016f98412e)