stride3d/stride · error · ArgumentException

Type [ ] is not supported as a modifiable collection

Error message

Type [{type}] is not supported as a modifiable collection

What it means

OldCollectionDescriptor's constructor inspects the type for supported collection interfaces (IList/ICollection/arrays with indexers, etc.). If the type implements none of the supported modifiable collection shapes, it throws ArgumentException 'Type [{type}] is not supported as a modifiable collection'. The descriptor needs known Add/Remove/Insert/indexer methods to support editing.

Solutions

  1. Make the type implement IList or ICollection<T> (e.g. inherit from List<T> or Collection<T>).
  2. Use a supported collection type (List<T>, T[], ObservableCollection<T>, HashSet<T>) instead of a custom one.
  3. Register the type with the correct descriptor (ObjectDescriptor or SetDescriptor) if it is not a collection.

Example fix

// before
public class MyItems { /* no collection interface */ }
// after
public class MyItems : List<Item> { }
Defensive patterns

Strategy: validation

Validate before calling

bool supported = type.IsArray
    || typeof(IList).IsAssignableFrom(type)
    || (type.IsGenericType && typeof(ICollection<>).IsAssignableFrom(type.GetGenericTypeDefinition().MakeGenericType(type.GetGenericArguments())));
if (!supported) throw new InvalidOperationException($"{type} is not a supported modifiable collection");

Type guard

static bool IsModifiableCollection(Type t) => t.IsArray || typeof(IList).IsAssignableFrom(t) || t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>));

Try / catch

try { var d = new OldCollectionDescriptor(factory, type, emit, conv); }
catch (ArgumentException ex) when (ex.Message.Contains("not supported as a modifiable collection")) { /* fall back to ObjectDescriptor */ }

Prevention

When it happens

Trigger: Constructing OldCollectionDescriptor for a type that is not a recognized modifiable collection — e.g. IEnumerable-only types, custom collections implementing neither IList nor ICollection<T>, dictionaries routed to the wrong descriptor.

Common situations: Trying to serialize/edit read-only sequences (yield-return iterators, LINQ query results); custom collection classes missing standard interfaces; types registered with the wrong descriptor factory branch.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/a6e9f06551671633. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Reflection/TypeDescriptors/OldCollectionDescriptor.cs:115

                var removeAt = type.GetMethod(nameof(IList<object>.RemoveAt), [typeof(int)]);
                if (removeAt != null)
                    removeAtMethod = (obj, index) => removeAt.Invoke(obj, [index]);

                var getItem = type.GetMethod("get_Item", [typeof(int)]);
                if (getItem != null)
                    getIndexedItemMethod = (obj, index) => getItem.Invoke(obj, [index]);

                var setItem = type.GetMethod("set_Item", [typeof(int), ElementType]);
                if (setItem != null)
                    setIndexedItemMethod = (obj, index, value) => setItem.Invoke(obj, [index, value]);

                HasIndexerAccessors = getItem != null && setItem != null;
            }
        }
        else
        {
            throw new ArgumentException($"Type [{type}] is not supported as a modifiable collection");
        }

        HasAdd = addMethod != null;
        HasRemove = removeMethod != null;
        HasInsert = insertMethod != null;
        HasRemoveAt = removeAtMethod != null;
    }

    public override void Initialize(IComparer<object> keyComparer)
    {
        base.Initialize(keyComparer);

        IsPureCollection = Count == 0;
    }

    public override DescriptorCategory Category => DescriptorCategory.Collection;

    /// <summary>

View on GitHub (pinned to 96fad776d2)