dotnet/wpf · error · InvalidOperationException

SR.UIElement_Layout_InfinityArrange

Error message

SR.UIElement_Layout_InfinityArrange

What it means

UIElement.Arrange throws an InvalidOperationException (SR.UIElement_Layout_InfinityArrange, formatted with the parent's and element's type names) when finalRect contains PositiveInfinity or NaN in width/height. Arrange requires a finite rectangle; the message names the parent whose layout produced the bad rect.

Solutions

  1. In the parent's ArrangeOverride, clamp finalRect dimensions to finite values before calling child.Arrange.
  2. Ensure MeasureOverride returns finite sizes so Arrange inherits sane constraints.
  3. For unbounded content, use scroll-aware patterns (ScrollViewer + finite viewport math) instead of passing infinity.

Example fix

// before
child.Arrange(new Rect(point, finalSize)); // finalSize may be infinite
// after
var w = double.IsInfinity(finalSize.Width) ? child.DesiredSize.Width : finalSize.Width;
var h = double.IsInfinity(finalSize.Height) ? child.DesiredSize.Height : finalSize.Height;
child.Arrange(new Rect(point, new Size(w, h)));
Defensive patterns

Strategy: validation

Validate before calling

if (double.IsInfinity(finalRect.Width) || double.IsInfinity(finalRect.Height) || double.IsNaN(finalRect.Width) || double.IsNaN(finalRect.Height))
    finalRect = new Rect(finalRect.Location, new Size(child.DesiredSize.Width, child.DesiredSize.Height));

Type guard

bool IsValidArrangeRect(Rect r) => double.IsFinite(r.Width) && double.IsFinite(r.Height) && !double.IsNaN(r.Width) && !double.IsNaN(r.Height);

Try / catch

try { child.Arrange(finalRect); } catch (InvalidOperationException ex) when (ex.Message.Contains("Arrange")) { /* clamp rect and retry */ }

Prevention

When it happens

Trigger: A parent panel passing an infinite/NaN finalRect to child.Arrange(...), typically because its own measure or available size was infinite; custom ArrangeOverride implementations forwarding infinite finalSize.

Common situations: Custom panels arranging children in infinite scroll/viewport scenarios without clamping; elements inside ScrollViewer whose ArrangeOverride passes raw unbounded sizes; broken custom layouts after refactor.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/5db523db1c50ce68. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/UIElement.cs:799

            try
            {
                //             VerifyAccess();

                // Disable reentrancy during the arrange pass.  This is because much work is done
                // during arrange - such as formatting PTS stuff, creating
                // fonts, etc.  Generally speaking, we cannot survive reentrancy in these code
                // paths.
                using (Dispatcher.DisableProcessing())
                {
                    //enforce that Arrange can not come with Infinity size or NaN
                    if (double.IsPositiveInfinity(finalRect.Width)
                        || double.IsPositiveInfinity(finalRect.Height)
                        || double.IsNaN(finalRect.Width)
                        || double.IsNaN(finalRect.Height)
                      )
                    {
                        DependencyObject parent = GetUIParent() as UIElement;
                        throw new InvalidOperationException(
                            SR.Format(
                                SR.UIElement_Layout_InfinityArrange,
                                    (parent == null ? "" : parent.GetType().FullName),
                                    this.GetType().FullName));
                    }


                    //if Collapsed, we should not Arrange, keep dirty bit but remove request
                    if (this.Visibility == Visibility.Collapsed
                        || ((Visual)this).CheckFlagsAnd(VisualFlags.IsLayoutSuspended))
                    {
                        //reset arrange request.
                        if (ArrangeRequest != null)
                            ContextLayoutManager.From(Dispatcher).ArrangeQueue.Remove(this);

                        //  remember though that parent tried to arrange at this rect
                        //  in case when later this element is called to arrange incrementally
                        //  it has up-to-date information stored in _finalRect

View on GitHub (pinned to 81131a70a4)