Unity-Technologies/UnityCsReference · error · InvalidOperationException

Number of rows does not match number of row rects. Did you r

Error message

Number of rows does not match number of row rects. Did you remember to update the row rects when BuildRootAndRows was called? Number of rows: {0}, number of custom row rects: {1}. Falling back to fixed row height.

What it means

Thrown during visible-row computation (in TreeViewControlGUI) when the number of rows (rowCount) does not match the number of custom row rects (m_RowRects.Count). This means BuildRows changed the row count but RefreshRowRects was not called to recompute the per-row Rect array, leaving the geometry inconsistent. The message says it 'falls back' but the code actually nulls m_RowRects and throws.

Source

Thrown at Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlGUI.cs:275

                {
                    base.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible);
                    return;
                }

                var rowCount = m_TreeView.data.rowCount;
                if (rowCount == 0 || Mathf.Approximately(m_TreeView.visibleRect.height, 0.0f))
                {
                    firstRowVisible = lastRowVisible = -1;
                    return;
                }

                if (rowCount != m_RowRects.Count)
                {
                    var errorMessage = string.Format(
                        "Number of rows does not match number of row rects. Did you remember to update the row rects when BuildRootAndRows was called? Number of rows: {0}, number of custom row rects: {1}. Falling back to fixed row height.",
                        rowCount, m_RowRects.Count);
                    m_RowRects = null;
                    throw new InvalidOperationException(errorMessage);
                }

                float topPixel = m_TreeView.state.scrollPos.y;
                float heightInPixels = m_TreeView.visibleRect.height;

                int firstVisible = -1;
                int lastVisible = -1;
                for (int i = 0; i < m_RowRects.Count; ++i)
                {
                    bool visible =  ((m_RowRects[i].y > topPixel && (m_RowRects[i].y < topPixel + heightInPixels))) ||
                        ((m_RowRects[i].yMax > topPixel && (m_RowRects[i].yMax < topPixel + heightInPixels)));

                    if (visible)
                    {
                        if (firstVisible == -1)
                            firstVisible = i;
                        lastVisible = i;
                    }

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Call treeView.Reload() then treeView.RefreshCustomRowHeights() whenever the underlying data changes.
  2. Ensure BuildRows and GetCustomRowHeight are consistent in the row count they assume.
  3. Override BuildRows to call RefreshCustomRowHeights internally if rows change, or ensure m_RowRects is rebuilt in BuildRows.

Example fix

// before
// data changed, rows differ from rects
OnDataChanged();

// after
OnDataChanged();
treeView.Reload();
treeView.RefreshCustomRowHeights(); // recomputes m_RowRects to match rows
Defensive patterns

Strategy: validation

Validate before calling

treeView.Reload();
treeView.RefreshCustomRowHeights(); // keeps m_RowRects in sync with row count

Prevention

When it happens

Trigger: Overriding GetCustomRowHeight and changing row data (Reload/BuildRows) without calling RefreshCustomRowHeights afterward; BuildRows returning a different count than when rects were last computed; rows added/removed between reload and render.

Common situations: Dynamic TreeView where items are added/removed at runtime without calling Reload + RefreshCustomRowHeights; custom BuildRows that filters rows differently each call.

Related errors


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