stride3d/stride · error · InvalidOperationException
An IObjectNode was expected when processing the path
Error message
An IObjectNode was expected when processing the path [{path}] What it means
AssetPropertyGraph.ResolveObjectPath throws this InvalidOperationException while walking a YamlAssetPath: an element was resolved through a reference node, and the node reached is not an IObjectNode (it has no indexed children) even though more path elements follow. This signals the serialized path no longer matches the live node structure — typically a stale path after the object model changed.
Solutions
- Regenerate the asset path (re-diff or re-record the override) against the current object model
- Upgrade/fix the asset file so the stored path matches the current schema
- Validate the path node-by-node with TryGetNode-style lookups before applying, and skip/repair invalid paths
- Roll back the schema change that altered the referenced object's shape
Example fix
// before
var node = graph.ResolveObjectPath(path); // throws on stale path
// after
if (!graph.TryResolvePath(path, out var node)) { Console.Error.WriteLine($"Stale path {path}; re-recording override"); return; } Defensive patterns
Strategy: validation
Validate before calling
bool pathLooksValid = path.Elements.All(el => el.Type switch {
YamlAssetPath.ElementType.MemberId => true,
_ => true }); // validate segment-by-segment against the live graph before applying Type guard
bool isObjectNode = node is IObjectNode;
Try / catch
try { var node = graph.ResolveObjectPath(path); } catch (InvalidOperationException ex) when (ex.Message.Contains("IObjectNode was expected")) { // path is stale: re-diff or skip this override } Prevention
- Re-record saved overrides after upgrading the engine or changing asset schemas
- Do not hand-edit YAML paths in asset files
- Version-check stored diffs before applying them
When it happens
Trigger: Resolving a YamlAssetPath whose MemberId/Index element targets an IsReference node whose Target is not an IObjectNode; usually paths loaded from old YAML diffs, overridden-value paths, or paths constructed against a different object layout.
Common situations: Applying saved overrides/patches after the asset class schema changed (property turned from collection to reference or vice versa); version upgrades of the engine changing object shapes; hand-crafted paths in migration scripts.
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
- An IMemberNode was expected when processing the path
- Unable to find the base
- Unable to find the graph corresponding to the base part
- The base is unset for the current node.
- An error occurred while adding an item to the node, see the…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/c716e315c581ee9c.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets.Quantum/AssetPropertyGraph.cs:360
if (currentNode.IsReference)
{
if (currentNode is not IMemberNode memberNode) throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]");
currentNode = (IAssetNode?)memberNode.Target;
}
if (currentNode is not IObjectNode objectNode) throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
var name = item.AsMember();
currentNode = (IAssetNode?)objectNode.TryGetChild(name);
break;
}
case YamlAssetPath.ElementType.Index:
{
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;View on GitHub (pinned to 96fad776d2)