XINCGer/Unity3DTraining · error · ArgumentException

FieldDescriptors can only be compared to other…

Error message

FieldDescriptors can only be compared to other FieldDescriptors for fields of the same message type.

What it means

FieldDescriptor.CompareTo orders fields by field number, but only fields of the SAME message type have a meaningful order. If the other descriptor belongs to a different containing type, it throws ArgumentException. It exists so fields can be sorted (e.g. for reflection-based serialization order).

Solutions

  1. Group descriptors by ContainingType and only sort within one message type.
  2. Use FieldNumber for ordering instead of CompareTo when comparing across types.
  3. Guard the comparison with a ContainingType equality check before calling CompareTo.

Example fix

// before
list.Sort((a, b) => a.CompareTo(b)); // mixed types
// after
list.Sort((a, b) => a.ContainingType == b.ContainingType
    ? a.FieldNumber.CompareTo(b.FieldNumber)
    : string.CompareOrdinal(a.ContainingType.FullName, b.ContainingType.FullName));
Defensive patterns

Strategy: type-guard

Validate before calling

if (a.ContainingType != b.ContainingType)
    throw new InvalidOperationException("Cannot CompareTo fields of different message types");

Type guard

bool SameMessage(a, b) => ReferenceEquals(a.ContainingType, b.ContainingType);

Try / catch

int cmp;
try { cmp = a.CompareTo(b); }
catch (ArgumentException) { cmp = string.CompareOrdinal(a.ContainingType.FullName, b.ContainingType.FullName); }

Prevention

When it happens

Trigger: Calling fieldDescriptor1.CompareTo(fieldDescriptor2) where the two descriptors have different ContainingType references, e.g. sorting a mixed list built from two message types, or comparing a field of message A with one of message B.

Common situations: Reflection code that collects FieldDescriptors across multiple message types into one list and sorts it; dictionary/set comparisons relying on IComparable across message types.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12). Data as JSON: /api/errors/7dd0fca54230fdbd. Report an issue: GitHub.

Appendix: source

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

        public int FieldNumber
        {
            get
            {
                return Proto.Number;
            }
        }

        /// <summary>
        /// Compares this descriptor with another one, ordering in "canonical" order
        /// which simply means ascending order by field number. <paramref name="other"/>
        /// must be a field of the same type, i.e. the <see cref="ContainingType"/> of
        /// both fields must be the same.
        /// </summary>
        public int CompareTo(FieldDescriptor other)
        {
            if (other.ContainingType != ContainingType)
            {
                throw new ArgumentException("FieldDescriptors can only be compared to other FieldDescriptors " +
                                            "for fields of the same message type.");
            }
            return FieldNumber - other.FieldNumber;
        }

        /// <summary>
        /// For enum fields, returns the field's type.
        /// </summary>
        public EnumDescriptor EnumType
        {
            get
            {
                if (fieldType != FieldType.Enum)
                {
                    throw new InvalidOperationException("EnumType is only valid for enum fields.");
                }
                return enumType;
            }

View on GitHub (pinned to 016f98412e)