XINCGer/Unity3DTraining · error · InvalidOperationException
MessageType is only valid for message fields.
Error message
MessageType is only valid for message fields.
What it means
The FieldDescriptor.MessageType property only holds a value when the field's type is FieldType.Message. Reading it on any other field throws InvalidOperationException. Non-message fields have no nested message descriptor.
Solutions
- Check field.FieldType == FieldType.Message before accessing MessageType.
- Restrict MessageType access to the message branch of your field-type handling code.
- For fields that may be either, branch on FieldType before accessing either descriptor property.
Example fix
// before var messageType = field.MessageType; // after var messageType = field.FieldType == FieldType.Message ? field.MessageType : null;
Defensive patterns
Strategy: type-guard
Validate before calling
var messageType = field.FieldType == FieldType.Message ? field.MessageType : null;
Type guard
bool TryGetMessageType(FieldDescriptor f, out MessageDescriptor md)
{ md = f.FieldType == FieldType.Message ? f.MessageType : null; return md != null; } Try / catch
MessageDescriptor md = null;
try { md = field.MessageType; }
catch (InvalidOperationException) { /* not a message field */ } Prevention
- Check FieldType == FieldType.Message before dereferencing MessageType.
- Never assume every field of a message contains a nested message.
- Use non-throwing helpers in generic reflection code.
When it happens
Trigger: Accessing descriptor.MessageType on a field whose FieldType is primitive, string, bytes, or enum — commonly in reflection code that walks fields assuming every field references a message.
Common situations: Generic serialization/diff tools that dereference MessageType for every field; groups/enum fields mishandled as messages.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- EnumType is only valid for enum fields.
- SkipLastField cannot be called at the end of a stream
- SpaceLeft can only be called on CodedOutputStreams that are…
- Unexpected token type:
- FieldDescriptors can only be compared to other…
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/c5bf1234d799fa2e.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/Reflection/FieldDescriptor.cs:288
{
if (fieldType != FieldType.Enum)
{
throw new InvalidOperationException("EnumType is only valid for enum fields.");
}
return enumType;
}
}
/// <summary>
/// For embedded message and group fields, returns the field's type.
/// </summary>
public MessageDescriptor MessageType
{
get
{
if (fieldType != FieldType.Message)
{
throw new InvalidOperationException("MessageType is only valid for message fields.");
}
return messageType;
}
}
/// <summary>
/// Look up and cross-link all field types etc.
/// </summary>
internal void CrossLink()
{
if (Proto.TypeName != "")
{
IDescriptor typeDescriptor =
File.DescriptorPool.LookupSymbol(Proto.TypeName, this);
if (Proto.Type != 0)
{
// Choose field type based on symbol.View on GitHub (pinned to 016f98412e)