{"record":{"id":"32df7c2c7e3ce069","repo":"stride3d/stride","slug":"an-iobjectnode-was-expected-when-processing-the-path-path-32df7c","errorCode":null,"errorMessage":"An IObjectNode was expected when processing the path [{path}]","messagePattern":"An IObjectNode was expected when processing the path \\[(.+?)\\]","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets.Quantum/Visitors/AssetNodeMetadataCollectorBase.cs","lineNumber":79,"sourceCode":"    /// </summary>\n    /// <param name=\"path\">The path to convert.</param>\n    /// <param name=\"inNonIdentifiableType\">If greater than zero, will ignore collection item ids and write indices instead.</param>\n    /// <returns>An instance of <see cref=\"YamlAssetPath\"/> corresponding to the given <paramref name=\"path\"/>.</returns>\n    public static YamlAssetPath ConvertPath(GraphNodePath path, int inNonIdentifiableType = 0)\n    {\n        ArgumentNullException.ThrowIfNull(path);\n        var currentNode = (IAssetNode)path.RootNode;\n        var result = new YamlAssetPath();\n        var i = 0;\n        foreach (var item in path.Path)\n        {\n            switch (item.Type)\n            {\n                case GraphNodePath.ElementType.Member:\n                {\n                    var member = item.Name;\n                    result.PushMember(member);\n                        if (currentNode is not IObjectNode objectNode) throw new InvalidOperationException($\"An IObjectNode was expected when processing the path [{path}]\");\n                        currentNode = (IAssetNode?)objectNode.TryGetChild(member);\n                    break;\n                }\n                case GraphNodePath.ElementType.Target:\n                {\n                    if (i < path.Path.Count - 1)\n                    {\n                            if (currentNode is not IMemberNode targetingMemberNode) throw new InvalidOperationException($\"An IMemberNode was expected when processing the path [{path}]\");\n                            currentNode = (IAssetNode?)targetingMemberNode.Target;\n                    }\n                    break;\n                }\n                case GraphNodePath.ElementType.Index:\n                {\n                    var index = item.Index;\n                        if (currentNode is not AssetObjectNode objectNode) throw new InvalidOperationException($\"An IObjectNode was expected when processing the path [{path}]\");\n                        if (inNonIdentifiableType > 0 || !CollectionItemIdHelper.HasCollectionItemIds(objectNode.Retrieve()))\n                    {","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets.Quantum/Visitors/AssetNodeMetadataCollectorBase.cs#L61-L97","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nresult.PushMember(member); // assumes object node\n// after\nif (currentNode is IObjectNode objectNode && objectNode.TryGetChild(member) != null)\n    result.PushMember(member);\nelse\n    return null; // path no longer matches graph","handlingStrategy":"type-guard","validationCode":"if (path.Path.Any(s => s.Type == GraphNodePath.ElementType.Member))\n    rebuilt = AssetNodeMetadataCollectorBase.RebuildFromGraph(asset); // prefer regenerated paths","typeGuard":"static bool CanPushMember(IGraphNode n) => n is IObjectNode;","tryCatchPattern":"try { result = collector.ConvertPath(path); }\ncatch (InvalidOperationException) { result = null; // stale path }","preventionTips":["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"],"tags":["stride","quantum","assets","paths","graph"],"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"}