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

  1. Check field.FieldType == FieldType.Message before accessing MessageType.
  2. Restrict MessageType access to the message branch of your field-type handling code.
  3. 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

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


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)