dotnet/wpf · error · InvalidOperationException
SR.Format(SR.LayoutManager_DeepRecursion, TreeLevelLimit)
Error message
SR.Format(SR.LayoutManager_DeepRecursion, TreeLevelLimit)
What it means
Visual.TreeLevel limits the visual tree depth to TreeLevelLimit (about 2047 levels, stored in flag bits). Setting it beyond the limit throws InvalidOperationException(LayoutManager_DeepRecursion), preventing stack overflow during recursive layout/visual-tree traversal.
Solutions
- Flatten or restructure the visual tree to reduce depth
- Detect and break cycles in data/templates driving recursive nesting
- Use non-visual data structures (e.g. virtualization/ItemsControl) instead of deep visual nesting
Example fix
// before
Visual current = root;
for (int i = 0; i < 5000; i++) { var v = new Border(); current.AddVisualChild(v); current = v; }
// after
var items = new ItemsControl { ItemsSource = Enumerable.Range(0, 5000) }; // flat, virtualized Defensive patterns
Strategy: validation
Validate before calling
int Depth(Visual v) { int d = 0; for (DependencyObject p = v; p != null; p = VisualTreeHelper.GetParent(p)) d++; return d; } // ensure < ~2047 Type guard
bool DepthWithinLimit(Visual v) => Depth(v) < 2000;
Try / catch
try { /* build tree */ } catch (InvalidOperationException ex) when (ex.Message.Contains("recursion") || ex.Message.Contains("deep")) { /* flatten tree */ } Prevention
- Avoid unbounded recursive visual nesting
- Break data/template cycles driving recursion
- Use virtualization for deep data
When it happens
Trigger: Building or embedding a visual tree deeper than TreeLevelLimit; programmatically adding nested visuals in an unbounded recursive structure.
Common situations: Recursive data-bound templates with cyclic or self-referencing data; pathological nested layouts generated from recursive algorithms.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- ' ' is not a Visual or Visual3D.
- inverse ? SR.Visual_NotADescendant : SR.Visual_NotAnAncestor
- Page can have only Window or Frame as parent.
- Specified index is out of range or child at index is null…
- Specified index is out of range or child at index is null…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/4d809fbb53a3df17.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Visual.cs:2733
}
//This is used by LayoutManager as a perf optimization for layout updates.
//During layout updates, LM needs to find which areas of the visual tree
//are higher in the tree - they have to be processed first to avoid multiple
//updates of lower descendants. The tree level counter is maintained by
//UIElement.PropagateResume/SuspendLayout methods and uses 8 bits in VisualFlags to
//keep the count.
internal uint TreeLevel
{
get
{
return ((uint)_flags & 0xFFE00000) >> 21;
}
set
{
if(value > TreeLevelLimit)
{
throw new InvalidOperationException(SR.Format(SR.LayoutManager_DeepRecursion, TreeLevelLimit));
}
_flags = (VisualFlags)(((uint)_flags & 0x001FFFFF) | (value << 21));
}
}
#endregion VisualChildren
#region VisualParent
/// <summary>
/// Returns the parent of this Visual. Parent may be either a Visual or Visual3D.
/// </summary>
protected DependencyObject VisualParent
{
getView on GitHub (pinned to 81131a70a4)