{"record":{"id":"9bed7b8df76c4588","repo":"stride3d/stride","slug":"a-node-of-the-path-is-null-but-is-not-the-last-node","errorCode":null,"errorMessage":"A node of the path is null but is not the last node.","messagePattern":"A node of the path is null but is not the last node\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Quantum/GraphNodePath.cs","lineNumber":172,"sourceCode":"            {\n                current = path.RootNode;\n            }\n            else\n            {\n                var element = path.path[index];\n                current = element.Type switch\n                {\n                    ElementType.Member => ((IObjectNode)Current)[element.Name!],\n                    ElementType.Target => ((IMemberNode)Current).Target,\n                    ElementType.Index => ((IObjectNode)Current).ItemReferences?[element.Index].TargetNode,\n                    _ => throw new ArgumentOutOfRangeException(),\n                };\n            }\n            ++index;\n\n            // If a node that is not the last one is null, we cannot process the path.\n            if (current is null && index < path.path.Count)\n                throw new InvalidOperationException(\"A node of the path is null but is not the last node.\");\n\n            return true;\n        }\n\n        public void Reset()\n        {\n            index = -1;\n        }\n\n        public readonly IGraphNode Current => current!;\n\n        readonly object IEnumerator.Current => current!;\n    }\n\n    private const int DefaultCapacity = 16;\n    private readonly List<NodePathElement> path;\n\n    private GraphNodePath(IGraphNode rootNode, int defaultCapacity)","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Quantum/GraphNodePath.cs#L154-L190","documentation":"GraphNodePath's enumerator (MoveNext) throws InvalidOperationException when a node in the middle of the path resolves to null while more path elements remain. A null intermediate node means the remaining path segments cannot be resolved, so continuing would be meaningless.","triggerScenarios":"Enumerating a GraphNodePath whose chained nodes (member/index/target lookups) produced null for a non-final node — e.g. a member node was removed from its parent while a path referencing it was still being walked.","commonSituations":"Holding stale node paths after the model changed (member deleted, list cleared); iterating paths concurrently with graph mutation; resolving paths against partially built containers.","solutions":["Re-resolve/rebuild the node path after model changes instead of reusing the stale one","Check node existence (e.g. NodeContainer.TryGetNode) before walking the remaining path","Avoid mutating the graph while enumerating paths; snapshot first","Catch InvalidOperationException during iteration and treat the path as invalid"],"exampleFix":"// before\nforeach (var node in stalePath) { ... }\n// after\nif (NodeContainer.TryGetNode(path, out var node)) { /* use node */ }","handlingStrategy":"validation","validationCode":"if (!NodeContainer.TryGetNode(path, out var node)) throw new InvalidOperationException(\"Path no longer resolves; rebuild it\");","typeGuard":null,"tryCatchPattern":"try { foreach (var n in graphNodePath) { ... } } catch (InvalidOperationException ex) when (ex.Message.Contains(\"path is null\")) { rebuildPath(); }","preventionTips":["Rebuild node paths after any graph mutation","Avoid iterating paths while the model is being changed","Re-resolve paths instead of caching them across frames"],"tags":["path","null","quantum"],"backgroundTag":"internal-invariant-violation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}