Unity-Technologies/UnityCsReference · critical · NullReferenceException

RefreshRows should set valid list of rows.

Error message

RefreshRows should set valid list of rows.

What it means

Thrown by FetchData after calling BuildRows when the returned rows list is null. BuildRows (or its default implementation, which calls AddExpandedRows) must return a valid IList of rows; null means the row-building step failed or was not implemented correctly.

Source

Thrown at Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDataSource.cs:64

                }
            }

            public override void FetchData()
            {
                // Set before BuildRoot and BuildRows so we can call GetRows in them without recursion
                m_NeedRefreshRows = false;

                // Root
                if (m_RootItem == null)
                {
                    m_RootItem = m_Owner.BuildRoot();
                    ValidateRootItem();
                }

                // Rows
                m_Rows = m_Owner.BuildRows(m_RootItem);
                if (m_Rows == null)
                    throw new NullReferenceException("RefreshRows should set valid list of rows.");

                // Custom row rects
                if (m_Owner.m_OverriddenMethods.hasGetCustomRowHeight)
                    m_Owner.m_GUI.RefreshRowRects(m_Rows);
            }

            public void SearchFullTree(string search, List<TreeViewItem<TIdentifier>> result)
            {
                if (string.IsNullOrEmpty(search))
                    throw new ArgumentException("Invalid search: cannot be null or empty", "search");

                if (result == null)
                    throw new ArgumentException("Invalid list: cannot be null", "result");

                var stack = new Stack<TreeViewItem<TIdentifier>>();
                stack.Push(m_RootItem);
                while (stack.Count > 0)
                {

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Override BuildRows and always return a non-null IList (return an empty list when there are no rows).
  2. If using the default BuildRows, ensure rootItem is valid and has expandable children.
  3. Replace 'return null;' with 'return new List<TreeViewItem<TIdentifier>>();' in early-exit branches.

Example fix

// before
protected override IList<TreeViewItem<int>> BuildRows(TreeViewItem<int> root)
{
    if (data.Count == 0) return null;
    // ...
}

// after
protected override IList<TreeViewItem<int>> BuildRows(TreeViewItem<int> root)
{
    var rows = new List<TreeViewItem<int>>();
    if (data.Count == 0) return rows;
    // ...
    return rows;
}
Defensive patterns

Strategy: validation

Validate before calling

protected override IList<TreeViewItem<int>> BuildRows(TreeViewItem<int> root)
{
    var rows = new List<TreeViewItem<int>>();
    // populate...
    return rows; // never null
}

Type guard

static bool IsValidRows<T>(IList<TreeViewItem<T>> rows) => rows != null;

Prevention

When it happens

Trigger: Overriding BuildRows and returning null; not overriding BuildRows but rootItem having no expanded rows in a path that returns null; BuildRows returning null conditionally when data is empty.

Common situations: Custom BuildRows override that returns null on an early-exit path; data source returning null from an internal helper; overriding BuildRows to do custom filtering but forgetting the return.

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/d291946bf328cc8b. Report an issue: GitHub.