{"record":{"id":"8bb8c01f793d87f6","repo":"Unity-Technologies/UnityCsReference","slug":"invalid-tree-for-finding-descendants-ensure-a-com","errorCode":null,"errorMessage":"Invalid tree for finding descendants: Ensure a complete tree when using this utillity method.","messagePattern":"Invalid tree for finding descendants: Ensure a complete tree when using this utillity method\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Editor/Mono/GUI/TreeView/TreeViewUtililty.cs","lineNumber":114,"sourceCode":"        }\n\n        // Assumes full tree\n        internal static void GetParentsBelowItem(TreeViewItem<TIdentifier> fromItem, HashSet<TIdentifier> parentsBelow)\n        {\n            if (fromItem == null)\n                throw new ArgumentNullException(\"fromItem\");\n\n            Stack<TreeViewItem<TIdentifier>> stack = new Stack<TreeViewItem<TIdentifier>>();\n            stack.Push(fromItem);\n\n            while (stack.Count > 0)\n            {\n                TreeViewItem<TIdentifier> current = stack.Pop();\n                if (current.hasChildren)\n                {\n                    parentsBelow.Add(current.id);\n                    if (LazyTreeViewDataSource<TIdentifier>.IsChildListForACollapsedParent(current.children))\n                        throw new InvalidOperationException(\"Invalid tree for finding descendants: Ensure a complete tree when using this utillity method.\");\n\n                    foreach (var foo in current.children)\n                    {\n                        stack.Push(foo);\n                    }\n                }\n            }\n        }\n\n        internal static void DebugPrintToEditorLogRecursive(TreeViewItem<TIdentifier> item)\n        {\n            if (item == null)\n                return;\n            System.Console.WriteLine(new System.String(' ', item.depth * 3) + item.displayName);\n\n            if (!item.hasChildren)\n                return;\n","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/Unity-Technologies/UnityCsReference/blob/225b0fbdb57cc17d094e8056b71f8314aba56f73/Editor/Mono/GUI/TreeView/TreeViewUtililty.cs#L96-L132","documentation":"GetDescendantsThatHaveChildren (and relatives) walks the tree to collect parent IDs, but it requires a fully expanded materialized tree. If it encounters a child list that is the special lazy/collapsed sentinel (a single-item placeholder produced by LazyTreeViewDataSource for a collapsed parent), it cannot know the real descendants and throws InvalidOperationException. The error tells you to provide a complete tree, i.e. expand parents before calling.","triggerScenarios":"Calling GetDescendantsThatHaveChildren on a tree built from a LazyTreeViewDataSource without expanding collapsed parents; running tree-walking utilities right after Reload before data source expansion; passing rows from GetRows() where collapsed parents still carry the lazy sentinel child.","commonSituations":"Custom tree view using lazy loading; a snapshot of the tree taken while some parents are collapsed; editor code that assumes all children are materialized.","solutions":["Ensure all relevant parents are expanded (SetExpanded on their ids) before invoking the descendant utility.","Use a fully materialized tree built via SetChildParentReferences from complete data rather than the lazy source.","If you only need visible rows, iterate GetRows() directly instead of walking the descendant tree.","Detect lazy sentinel children (LazyTreeViewDataSource<T>.IsChildListForACollapsedParent) and expand those parents first."],"exampleFix":"// before\nvar parents = new List<int>();\nTreeViewUtility<int>.GetDescendantsThatHaveChildren(root, parents);\n\n// after\nforeach (var id in collapsedParentIds)\n    treeViewState.expandedIDs.Add(id); // or SetExpanded\ntreeView.Reload();\nvar parents = new List<int>();\nTreeViewUtility<int>.GetDescendantsThatHaveChildren(root, parents);","handlingStrategy":"validation","validationCode":"// ensure parents expanded before walking descendants\nforeach (var id in idsToExpand)\n    state.expandedIDs.Add(id);\ntreeView.Reload();\n// now safe to call GetDescendantsThatHaveChildren","typeGuard":"static bool IsCompleteTree<T>(TreeViewItem<T> item) where T : unmanaged, IEquatable<T>\n{\n    if (item == null) return false;\n    if (item.hasChildren && LazyTreeViewDataSource<T>.IsChildListForACollapsedParent(item.children))\n        return false;\n    return true;\n}","tryCatchPattern":null,"preventionTips":["Expand collapsed parents before walking descendants.","Prefer materialized trees for utility passes rather than lazy sources.","Use GetRows() when only visible rows are needed."],"tags":["treeview","lazy-loading","invalid-state","editor-scripting","validation"],"backgroundTag":null,"analyzedSha":"225b0fbdb57cc17d094e8056b71f8314aba56f73","analyzedAt":"2026-08-13T19:07:19.849Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}