stride3d/stride · error · ArgumentException

The object is not an IEnumerable

Error message

The object is not an IEnumerable

What it means

ReferenceEnumerable.Refresh rebuilds the child references of a collection node. It retrieves the current value from the owner node and requires it to implement IEnumerable, since enumerable references only make sense for lists/dictionaries/sets/collections. If the node's value is not an IEnumerable (e.g. it changed to a scalar), it throws ArgumentException naming ownerNode.

Solutions

  1. Ensure the owner node's value implements IEnumerable before refreshing: check ownerNode.Retrieve() is IEnumerable.
  2. If the value legitimately changed to a non-collection, dispose/replace the ReferenceEnumerable rather than refreshing it.
  3. Fix the source property so its type stays a collection type for the lifetime of this reference.

Example fix

// before
((ReferenceEnumerable)node.References[0]).Refresh(node, nodeContainer);
// after
if (node.Retrieve() is IEnumerable)
    ((ReferenceEnumerable)node.References[0]).Refresh(node, nodeContainer);
Defensive patterns

Strategy: type-guard

Validate before calling

if (ownerNode.Retrieve() is IEnumerable)
    enumerableReference.Refresh(ownerNode, nodeContainer);

Type guard

bool CanRefresh(IGraphNode node) => node.Retrieve() is IEnumerable;

Try / catch

try { reference.Refresh(ownerNode, nodeContainer); }
catch (ArgumentException ex) when (ex.ParamName == "ownerNode") { /* value stopped being a collection; rebuild the reference instead */ }

Prevention

When it happens

Trigger: Calling ReferenceEnumerable.Refresh(ownerNode, nodeContainer) when ownerNode.Retrieve() returns an object that does not implement IEnumerable — e.g. the underlying property was reassigned from a List<T> to a scalar or non-collection object.

Common situations: Data-binding scenarios where an observable property changes type at runtime; node rebuild logic in custom NodeContainers; mutation of graph content from outside Quantum's expected contracts.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at sources/presentation/Stride.Core.Quantum/References/ReferenceEnumerable.cs:65

    /// <inheritdoc/>
    public ObjectReference this[NodeIndex index] => items[index];

    /// <summary>
    /// Indicates whether the reference contains the given index.
    /// </summary>
    /// <param name="index">The index to check.</param>
    /// <returns><c>True</c> if the reference contains the given index, <c>False</c> otherwise.</returns>
    /// <remarks>If it is an <see cref="ObjectReference"/> it will return true only for <c>null</c>.</remarks>
    public bool HasIndex(NodeIndex index)
    {
        return items?.ContainsKey(index) ?? false;
    }

    public void Refresh(IGraphNode ownerNode, NodeContainer nodeContainer)
    {
        var newObjectValue = ownerNode.Retrieve();
        if (newObjectValue is not IEnumerable) throw new ArgumentException("The object is not an IEnumerable", nameof(ownerNode));

        ObjectValue = newObjectValue;

        var newReferences = new HybridDictionary<NodeIndex, ObjectReference>();
        if (IsDictionary)
        {
            foreach (var item in (IEnumerable)ObjectValue)
            {
                var key = GetKey(item);
                var value = (ObjectReference)Reference.CreateReference(GetValue(item), ElementType, key, true);
                newReferences.Add(key, value);
            }
        }
        else
        {
            var i = 0;
            foreach (var item in (IEnumerable)ObjectValue)
            {

View on GitHub (pinned to 96fad776d2)