stride3d/stride · error · InvalidOperationException

SetDescriptor should not call function 'Insert'.

Error message

SetDescriptor should not call function 'Insert'.

What it means

SetDescriptor is a type descriptor for set-like collections (e.g. HashSet). Sets are unordered, so index-based mutation via Insert is not supported; the base CollectionDescriptor API contract is intentionally violated to fail fast. If code reaches this path it treats a set as an ordered list, which is a bug in the caller.

Solutions

  1. Use the Add(object set, object item) method instead of Insert for sets
  2. Check the descriptor type (e.g. descriptor is SetDescriptor) before calling index-based APIs
  3. If ordered semantics are needed, change the property type from a set to IList<T>

Example fix

// before
descriptor.Insert(mySet, 0, newItem);
// after
descriptor.Add(mySet, newItem);
Defensive patterns

Strategy: validation

Validate before calling

if (descriptor is SetDescriptor)
    descriptor.Add(set, item);
else
    descriptor.Insert(set, index, item);

Type guard

bool IsSetDescriptor(object d) => d is SetDescriptor;

Prevention

When it happens

Trigger: Calling SetDescriptor.Insert(set, index, value) directly, or generic code that iterates collection descriptors and calls Insert on every element type without checking it is an indexed list.

Common situations: Generic serialization/deserialization or data-binding code written for ListDescriptor re-used against a set descriptor; reflection-based editors attempting positional edits on HashSet<T> properties.

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/136a601aac37c4f4. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Reflection/TypeDescriptors/SetDescriptor.cs:92

    {
        return thisObject is null || isReadOnlyMethod.Invoke(thisObject);
    }

    /// <summary>
    /// Adds a value to a set.
    /// </summary>
    /// <param name="set">The set.</param>
    /// <param name="item">The item.</param>
    /// <exception cref="System.InvalidOperationException">No Add() method found on set [{0}].ToFormat(Type)</exception>
    public override void Add(object set, object? item)
    {
        ArgumentNullException.ThrowIfNull(set);
        addMethod.Invoke(set, item);
    }

    public override void Insert(object set, int index, object? value)
    {
        throw new InvalidOperationException("SetDescriptor should not call function 'Insert'.");
    }

    /// <summary>
    /// Remove a value from a set
    /// </summary>
    /// <param name="set">The set.</param>
    /// <param name="key">The key.</param>
    public override void Remove(object set, object? key)
    {
        ArgumentNullException.ThrowIfNull(set);
        removeMethod.Invoke(set, key);
    }

    public override void RemoveAt(object set, int index)
    {
        throw new InvalidOperationException($"{nameof(SetDescriptor)} should not call function 'RemoveAt'.");
    }

View on GitHub (pinned to 96fad776d2)