Unity-Technologies/UnityCsReference · error · ArgumentException

Specified enumType must be System.Enum

Error message

Specified enumType must be System.Enum

What it means

Thrown by the int-flag overload of EnumFlagsField when enumType.IsEnum is false. Unlike 184, this overload legitimately accepts an int value plus a Type, so the guard is the primary defense: callers supply a Type, and if it is not an enum the method refuses. The message correctly names 'enumType'.

Source

Thrown at Editor/Mono/EditorGUI.cs:4686

                throw new NotSupportedException(string.Format("Unsupported enum base type for {0}", enumType.Name));

            var id = GUIUtility.GetControlID(s_EnumFlagsField, FocusType.Keyboard, position);
            position = PrefixLabel(position, id, label);

            var flagsInt = EnumDataUtility.EnumFlagsToInt(enumData, enumValue);

            BeginChangeCheck();
            flagsInt = MaskFieldGUI.DoMaskField(position, id, flagsInt, enumData.displayNames, enumData.flagValues, style, out changedFlags, out changedToValue);
            if (!EndChangeCheck())
                return enumValue;

            return EnumDataUtility.IntToEnumFlags(enumType, flagsInt);
        }

        internal static int EnumFlagsField(Rect position, GUIContent label, int enumValue, Type enumType, bool includeObsolete, GUIStyle style)
        {
            if (!enumType.IsEnum)
                throw new ArgumentException("Specified enumType must be System.Enum", nameof(enumType));

            var enumData = EnumDataUtility.GetCachedEnumData(enumType, !includeObsolete);
            if (!enumData.serializable)
                // this is the same message used in SerializedPropertyEnumHelper.cpp
                throw new NotSupportedException(string.Format("Unsupported enum base type for {0}", enumType.Name));

            var id = GUIUtility.GetControlID(s_EnumFlagsField, FocusType.Keyboard, position);
            position = PrefixLabel(position, id, label);

            int changedFlags;
            bool changedToValue;
            return MaskFieldGUI.DoMaskField(position, id, enumValue, enumData.displayNames, enumData.flagValues, style, out changedFlags, out changedToValue, enumType.GetEnumUnderlyingType());
        }

        public static void ObjectField(Rect position, SerializedProperty property)
        {
            ObjectField(position, property, null, null, EditorStyles.objectField);
        }

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Guard with if (!type.IsEnum) before calling the int overload.
  2. Switch to the Enum-typed overload so the Type is always derived from a real enum value.
  3. Fix the registry/config to reference the actual enum type, not its underlying type.

Example fix

// before
EnumFlagsField(rect, label, flags, typeof(int), false, style);

// after
EnumFlagsField(rect, label, flags, typeof(MyFlagsEnum), false, style);
Defensive patterns

Strategy: type-guard

Validate before calling

if (enumType == null || !enumType.IsEnum) { Debug.LogError($"{enumType} is not an enum"); return enumValue; }

Type guard

static bool IsEnumType(Type t) => t != null && t.IsEnum;

Prevention

When it happens

Trigger: Calling EnumFlagsField(rect, label, someInt, someType, ...) where someType is typeof(int), typeof(string), or any non-enum. This is the realistic hit because the int overload is explicitly Type-driven.

Common situations: Generic bitfield editor utilities that store flags as int and pass a Type from a runtime registry; migrated code where the Type argument was left as the underlying integral type.

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/529af9b89e57aa5a. Report an issue: GitHub.