stride3d/stride · error · ArgumentException

Shouldn't call VisitCollection() to visit a set

Error message

Shouldn't call VisitCollection() to visit a set

What it means

DataVisitorBase.VisitCollection() is the generic visitor entry point for enumerable collections, but sets (ISet implementations) are described by a SetDescriptor with a different category and must be visited through VisitSet()/VisitCollectionItem semantics instead. The library throws ArgumentException to stop the traversal before it treats set members like ordinary list items, which would produce incorrect visit results.

Solutions

  1. Override or extend the visitor so set-category descriptors are routed to the set visiting path (e.g. VisitSet) instead of VisitCollection
  2. Check descriptor.Category == DescriptorCategory.Set before calling VisitCollection and handle it explicitly
  3. If the collection is not semantically a set in your domain, change the property type to a List<T>/array so it maps to a non-set CollectionDescriptor

Example fix

// before
visitor.VisitCollection(value, descriptor);
// after
if (descriptor.Category == DescriptorCategory.Set)
    VisitSet(value, descriptor);
else
    visitor.VisitCollection(value, descriptor);
Defensive patterns

Strategy: validation

Validate before calling

if (descriptor.Category == DescriptorCategory.Set)
    throw new InvalidOperationException("Route sets to the set-visiting path, not VisitCollection");

Type guard

bool IsSetDescriptor(CollectionDescriptor d) => d.Category == DescriptorCategory.Set;

Prevention

When it happens

Trigger: Calling visitor.VisitCollection(collection, descriptor) where descriptor.Category == DescriptorCategory.Set, e.g. visiting an object graph that contains HashSet<T>/ISet<T> members via the generic collection path (as dispatched from VisitObject).

Common situations: Custom reflection-based property walkers or serializers built on DataVisitor that did not override/dispatch the set case; adding a new set-typed property to an object that is being visited; upgrading Stride and reusing an old visitor that predates the set category distinction.

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 stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/e191db8d0b61fa73. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Design/Reflection/DataVisitorBase.cs:235

            var value = array.GetValue(i);
            CurrentPath.Push(descriptor, i);
            VisitArrayItem(array, descriptor, i, value, TypeDescriptorFactory.Find(value?.GetType() ?? descriptor.ElementType));
            CurrentPath.Pop();
        }
    }

    /// <inheritdoc />
    public virtual void VisitArrayItem(Array array, ArrayDescriptor descriptor, int index, object? item, ITypeDescriptor? itemDescriptor)
    {
        Visit(item, itemDescriptor);
    }

    /// <inheritdoc />
    public virtual void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)
    {
        if (descriptor.Category == DescriptorCategory.Set)
        {
            throw new ArgumentException("Shouldn't call VisitCollection() to visit a set");
        }
        var i = 0;

        // Make a copy in case VisitCollectionItem mutates something
        foreach (var item in collection.Cast<object>().ToList())
        {
            CurrentPath.Push(descriptor, i);
            VisitCollectionItem(collection, descriptor, i, item, TypeDescriptorFactory.Find(item?.GetType() ?? descriptor.ElementType));
            CurrentPath.Pop();
            i++;
        }
    }

    /// <inheritdoc />
    public virtual void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object? item, ITypeDescriptor? itemDescriptor)
    {
        Visit(item, itemDescriptor);
    }

View on GitHub (pinned to 96fad776d2)