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
ConvertPath walks a GraphNodePath step by step over the asset's node graph. For a Member step it must descend from an object node into a named child; if the current node is not an IObjectNode (e.g. it's an IMemberNode or primitive), the path is inconsistent with the graph and it throws.
Solutions
- Regenerate the GraphNodePath from the current asset graph rather than reusing persisted/serialized paths.
- Validate each step: before pushing a member, check currentNode is IObjectNode and TryGetChild(member) is non-null.
- Update the path after type/refactor changes to assets (member renamed or made scalar).
- Guard the caller with a check that the member exists on the node before converting the path.
Example fix
// before
result.PushMember(member); // assumes object node
// after
if (currentNode is IObjectNode objectNode && objectNode.TryGetChild(member) != null)
result.PushMember(member);
else
return null; // path no longer matches graph Defensive patterns
Strategy: type-guard
Validate before calling
if (path.Path.Any(s => s.Type == GraphNodePath.ElementType.Member))
rebuilt = AssetNodeMetadataCollectorBase.RebuildFromGraph(asset); // prefer regenerated paths Type guard
static bool CanPushMember(IGraphNode n) => n is IObjectNode;
Try / catch
try { result = collector.ConvertPath(path); }
catch (InvalidOperationException) { result = null; // stale path } Prevention
- Rebuild paths from the live graph instead of persisting them
- Regenerate override paths after asset type refactors
- Validate path steps against node types before conversion
When it happens
Trigger: ConvertPath is given a path whose Member element expects the previous/current node to be an IObjectNode, but the node at that position is a member node, target, or scalar — typically a malformed or stale GraphNodePath whose structure doesn't match the actual asset graph.
Common situations: Path built against an older asset version whose type was refactored (member moved/renamed into a scalar); a path targeting a member of an object-reference rather than an object node; corrupted override paths in serialized asset metadata.
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
- 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.
- No Collection item identifier associated to the given…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/32df7c2c7e3ce069.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets.Quantum/Visitors/AssetNodeMetadataCollectorBase.cs:79
/// </summary>
/// <param name="path">The path to convert.</param>
/// <param name="inNonIdentifiableType">If greater than zero, will ignore collection item ids and write indices instead.</param>
/// <returns>An instance of <see cref="YamlAssetPath"/> corresponding to the given <paramref name="path"/>.</returns>
public static YamlAssetPath ConvertPath(GraphNodePath path, int inNonIdentifiableType = 0)
{
ArgumentNullException.ThrowIfNull(path);
var currentNode = (IAssetNode)path.RootNode;
var result = new YamlAssetPath();
var i = 0;
foreach (var item in path.Path)
{
switch (item.Type)
{
case GraphNodePath.ElementType.Member:
{
var member = item.Name;
result.PushMember(member);
if (currentNode is not IObjectNode objectNode) throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
currentNode = (IAssetNode?)objectNode.TryGetChild(member);
break;
}
case GraphNodePath.ElementType.Target:
{
if (i < path.Path.Count - 1)
{
if (currentNode is not IMemberNode targetingMemberNode) throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]");
currentNode = (IAssetNode?)targetingMemberNode.Target;
}
break;
}
case GraphNodePath.ElementType.Index:
{
var index = item.Index;
if (currentNode is not AssetObjectNode objectNode) throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
if (inNonIdentifiableType > 0 || !CollectionItemIdHelper.HasCollectionItemIds(objectNode.Retrieve()))
{View on GitHub (pinned to 96fad776d2)