{"record":{"id":"b103f56ac7def358","repo":"Unity-Technologies/UnityCsReference","slug":"buildroot-should-set-a-valid-root-item","errorCode":null,"errorMessage":"BuildRoot should set a valid root item.","messagePattern":"BuildRoot should set a valid root item\\.","errorType":"exception","errorClass":"NullReferenceException","httpStatus":null,"severity":"critical","filePath":"Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDataSource.cs","lineNumber":36,"sourceCode":"            {\n                m_Owner = owner;\n\n                // The user should just create the visible rows, we create the hidden root\n                showRootItem = false;\n            }\n\n            public override void ReloadData()\n            {\n                // Clear root item to ensure client gets a call to BuildRoot every time Reload is called\n                m_RootItem = null;\n                base.ReloadData();\n            }\n\n            void ValidateRootItem()\n            {\n                if (m_RootItem == null)\n                {\n                    throw new NullReferenceException(\"BuildRoot should set a valid root item.\");\n                }\n                if (m_RootItem.depth != -1)\n                {\n                    Debug.LogError(\"BuildRoot should ensure the root item has a depth == -1. The visible items start at depth == 0.\");\n                    m_RootItem.depth = -1;\n                }\n                if (m_RootItem.children == null && !m_Owner.m_OverriddenMethods.hasBuildRows)\n                {\n                    throw new InvalidOperationException(\"TreeView: 'rootItem.children == null'. Did you forget to add children? If you intend to only create the list of rows (not the full tree) then you need to override: BuildRows, GetAncestors and GetDescendantsThatHaveChildren.\");\n                }\n            }\n\n            public override void FetchData()\n            {\n                // Set before BuildRoot and BuildRows so we can call GetRows in them without recursion\n                m_NeedRefreshRows = false;\n\n                // Root","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/Unity-Technologies/UnityCsReference/blob/225b0fbdb57cc17d094e8056b71f8314aba56f73/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDataSource.cs#L18-L54","documentation":"Thrown by ValidateRootItem (called after BuildRoot during FetchData) when the root item is still null. BuildRoot is a virtual method the subclass must override to construct and return the tree's root node; returning null (or not overriding it) leaves the tree empty and is a fatal data-source contract violation.","triggerScenarios":"Overriding BuildRoot but returning null; not overriding BuildRoot at all so the default returns null; BuildRoot returns null on a conditional path (e.g. when data is empty).","commonSituations":"Custom TreeView whose data source is empty/failed to load and BuildRoot returns null instead of an empty root; forgetting to implement BuildRoot in a new subclass; async data not yet loaded at Reload time.","solutions":["Override BuildRoot and always return a non-null root TreeViewItem with depth == -1.","When the data is empty, still return a valid root with an empty (not null) children list.","Ensure data loading completes before calling Reload."],"exampleFix":"// before\nprotected override TreeViewItem<int> BuildRoot()\n{\n    if (myData == null) return null;\n    // ...\n}\n\n// after\nprotected override TreeViewItem<int> BuildRoot()\n{\n    var root = new TreeViewItem<int>(0, -1, \"root\");\n    if (myData != null)\n    {\n        foreach (var d in myData)\n            root.AddChild(new TreeViewItem<int>(d.id, 0, d.name));\n    }\n    return root; // never null\n}","handlingStrategy":"validation","validationCode":"protected override TreeViewItem<int> BuildRoot()\n{\n    var root = new TreeViewItem<int>(0, -1, \"root\");\n    // populate children...\n    return root; // guaranteed non-null\n}","typeGuard":"static bool IsValidRoot<T>(TreeViewItem<T> root) => root != null && root.depth == -1;","tryCatchPattern":null,"preventionTips":["Always return a non-null root from BuildRoot, even when data is empty.","Set the root's depth to -1.","Load async data before calling Reload."],"tags":["unity","treeview","buildroot","null-reference","datasource"],"backgroundTag":null,"analyzedSha":"225b0fbdb57cc17d094e8056b71f8314aba56f73","analyzedAt":"2026-08-13T19:07:19.849Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}