{"record":{"id":"7d24f148ba7d37f8","repo":"stride3d/stride","slug":"the-object-is-not-an-ienumerable","errorCode":null,"errorMessage":"The object is not an IEnumerable","messagePattern":"The object is not an IEnumerable","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Quantum/References/ReferenceEnumerable.cs","lineNumber":65,"sourceCode":"\n    /// <inheritdoc/>\n    public ObjectReference this[NodeIndex index] => items[index];\n\n    /// <summary>\n    /// Indicates whether the reference contains the given index.\n    /// </summary>\n    /// <param name=\"index\">The index to check.</param>\n    /// <returns><c>True</c> if the reference contains the given index, <c>False</c> otherwise.</returns>\n    /// <remarks>If it is an <see cref=\"ObjectReference\"/> it will return true only for <c>null</c>.</remarks>\n    public bool HasIndex(NodeIndex index)\n    {\n        return items?.ContainsKey(index) ?? false;\n    }\n\n    public void Refresh(IGraphNode ownerNode, NodeContainer nodeContainer)\n    {\n        var newObjectValue = ownerNode.Retrieve();\n        if (newObjectValue is not IEnumerable) throw new ArgumentException(\"The object is not an IEnumerable\", nameof(ownerNode));\n\n        ObjectValue = newObjectValue;\n\n        var newReferences = new HybridDictionary<NodeIndex, ObjectReference>();\n        if (IsDictionary)\n        {\n            foreach (var item in (IEnumerable)ObjectValue)\n            {\n                var key = GetKey(item);\n                var value = (ObjectReference)Reference.CreateReference(GetValue(item), ElementType, key, true);\n                newReferences.Add(key, value);\n            }\n        }\n        else\n        {\n            var i = 0;\n            foreach (var item in (IEnumerable)ObjectValue)\n            {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Quantum/References/ReferenceEnumerable.cs#L47-L83","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the owner node's value implements IEnumerable before refreshing: check ownerNode.Retrieve() is IEnumerable.","If the value legitimately changed to a non-collection, dispose/replace the ReferenceEnumerable rather than refreshing it.","Fix the source property so its type stays a collection type for the lifetime of this reference."],"exampleFix":"// before\n((ReferenceEnumerable)node.References[0]).Refresh(node, nodeContainer);\n// after\nif (node.Retrieve() is IEnumerable)\n    ((ReferenceEnumerable)node.References[0]).Refresh(node, nodeContainer);","handlingStrategy":"type-guard","validationCode":"if (ownerNode.Retrieve() is IEnumerable)\n    enumerableReference.Refresh(ownerNode, nodeContainer);","typeGuard":"bool CanRefresh(IGraphNode node) => node.Retrieve() is IEnumerable;","tryCatchPattern":"try { reference.Refresh(ownerNode, nodeContainer); }\ncatch (ArgumentException ex) when (ex.ParamName == \"ownerNode\") { /* value stopped being a collection; rebuild the reference instead */ }","preventionTips":["Keep a node's value a collection type for the reference's lifetime","Re-create the reference rather than refreshing when the value's shape changes","Guard refreshes on type before calling"],"tags":["argument-validation","ienumerable","quantum"],"backgroundTag":"incompatible-source-type","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}