stride3d/stride · error · InvalidOperationException

An IMemberNode was expected when processing the path

Error message

An IMemberNode was expected when processing the path [{path}]

What it means

ResolveObjectPath throws this InvalidOperationException when processing an ItemId path element: the current node is not an IMemberNode, so memberNode.Target cannot be taken to continue the walk. The stored path expects to descend into a member at this point, but the live node tree has a different node kind there — a stale or mismatched path.

Solutions

  1. Re-record the override/diff against the current asset so paths match the live graph
  2. Fix the asset YAML or code so the path element targets an existing member
  3. Guard resolution with a try-pattern API or node-type checks before applying stored paths
  4. Align asset schema versions (re-save assets in the current engine version)

Example fix

// before
var node = graph.ResolveObjectPath(yamlPath); // stale after rename
// after
if (yamlPath.Elements.First().AsMember() == "OldName")
    yamlPath.Elements[0] = new YamlAssetPath.ElementMemberId("NewName");
var node = graph.ResolveObjectPath(yamlPath);
Defensive patterns

Strategy: try-catch

Validate before calling

var currentNode = graph.ResolveObjectPath(path.GetPrefix(path.Elements.Count - 1));
bool ok = currentNode is IMemberNode;

Type guard

bool isMemberNode = node is IMemberNode;

Try / catch

try { var node = graph.ResolveObjectPath(path); } catch (InvalidOperationException ex) when (ex.Message.Contains("IMemberNode was expected")) { // stale path: regenerate the diff for this asset }

Prevention

When it happens

Trigger: Resolving a YamlAssetPath with an ItemId element whose current node is not a member node: asset schema changed since the path was recorded, the path was built for a different asset type, or collection item ids were regenerated.

Common situations: Applying YAML diffs/overrides from an older Stride version to newer assets; manual edits to .sdt/.sdpkg YAML moving values; merging asset files where paths reference members that were renamed or removed.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at sources/assets/Stride.Core.Assets.Quantum/AssetPropertyGraph.cs:371

                    {
                        index = new NodeIndex(item.Value);
                        resolveOnIndex = true;
                        if (currentNode is not IMemberNode memberNode) throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]");
                        currentNode = (IAssetNode?)memberNode.Target;
                        if (currentNode.IsReference && i < path.Elements.Count - 1)
                        {
                            if (currentNode is not IObjectNode objNode) throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
                            currentNode = (IAssetNode?)objNode.IndexedTarget(new NodeIndex(item.Value));
                        }
                        break;
                    }
                case YamlAssetPath.ElementType.ItemId:
                    {
                        var ids = CollectionItemIdHelper.GetCollectionItemIds(currentNode.Retrieve());
                        var key = ids.GetKey(item.AsItemId());
                        index = new NodeIndex(key);
                        resolveOnIndex = false;
                        if (currentNode is not IMemberNode memberNode) throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]");
                        currentNode = (IAssetNode?)memberNode.Target;
                        if (currentNode.IsReference && i < path.Elements.Count - 1)
                        {
                            if (currentNode is not IObjectNode objNode) throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
                            currentNode = (IAssetNode?)objNode.IndexedTarget(new NodeIndex(key));
                        }
                        break;
                    }
                default:
                    throw new ArgumentOutOfRangeException();
            }

            // Something wrong happen, the node is unreachable.
            if (currentNode is null)
                return null;
        }

        return currentNode;

View on GitHub (pinned to 96fad776d2)