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
- Call treeView.Reload() then treeView.RefreshCustomRowHeights() whenever the underlying data changes.
- Ensure BuildRows and GetCustomRowHeight are consistent in the row count they assume.
- 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
- Call Reload + RefreshCustomRowHeights after any data change.
- Keep BuildRows and GetCustomRowHeight consistent in row count.
- Recompute custom row rects whenever rows are added or removed.
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
- Only call RefreshCustomRowHeights if you have overridden Get
- Input row index: {0} is invalid. Number of rows rects: {1}.
- GetCellRect can only be called when 'multiColumnHeader' has
- FindItem failed: root item has not been created yet
- Cannot call ReportAssetChanged outside of the OnAssetsModifi
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/7e67972efaa08ee6.
Report an issue: GitHub.