dotnet/wpf · error · ArgumentOutOfRangeException

SR.Visual_ArgumentOutOfRange

Error message

SR.Visual_ArgumentOutOfRange

What it means

Visual.GetVisualChild is a protected virtual that the base Visual implementation throws ArgumentOutOfRangeException from, indicating the index is outside the visual child count. Subclasses that do not override GetVisualChildCount/GetVisualChild (or that call it with an out-of-range index) hit this.

Solutions

  1. Ensure GetVisualChild is overridden consistently with GetVisualChildCount on custom visuals
  2. Re-read the child count immediately before each GetVisualChild call
  3. Clamp loop indices to VisualTreeHelper.GetChildrenCount(visual) at call time

Example fix

// before
for (int i = 0; i < 2; i++) GetVisualChild(i);
// after
int n = VisualTreeHelper.GetChildrenCount(this);
for (int i = 0; i < n; i++) GetVisualChild(i);
Defensive patterns

Strategy: validation

Validate before calling

if (index < 0 || index >= VisualTreeHelper.GetChildrenCount(visual)) return null;

Type guard

bool HasChildIndex(Visual v, int i) => i >= 0 && i < VisualTreeHelper.GetChildrenCount(v);

Try / catch

try { child = VisualTreeHelper.GetChild(v, i); } catch (ArgumentOutOfRangeException) { child = null; }

Prevention

When it happens

Trigger: Calling VisualTreeHelper.GetChild on a custom Visual whose GetVisualChildCount returns an inconsistent number, or invoking GetVisualChild(index) with index < 0 or >= child count on the base Visual.

Common situations: Custom visuals that override only one of VisualChildrenCount/GetVisualChild; iterating children with a stale or wrong count (e.g. count cached before tree changed).

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Visual.cs:2514

            }
        }

        /// <summary>
        ///   Derived class must implement to support Visual children. The method must return
        ///    the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1.
        ///
        ///    By default a Visual does not have any children.
        ///
        ///  Remark:
        ///       Need to lock down Visual tree during the callbacks.
        ///       During this virtual call it is not valid to modify the Visual tree.
        ///
        ///       It is okay to type this protected API to the 2D Visual.  The only 2D Visual with
        ///       3D childern is the Viewport3DVisual which is sealed
        /// </summary>
        protected virtual Visual GetVisualChild(int index)
        {
           throw new ArgumentOutOfRangeException(nameof(index), index, SR.Visual_ArgumentOutOfRange);
        }

        /// <summary>
        /// Returns the 2D child at index "index". This will fail for Visuals
        /// whose children are Visual3Ds.
        /// </summary>
        internal Visual InternalGetVisualChild(int index)
        {
            // Call the right virtual method.
            return GetVisualChild(index);
        }

        /// <summary>
        /// Returns the child at index "index" (in most cases this will be
        /// a Visual, but it some cases, Viewport3DVisual for instance,
        /// this is a Visual3D).
        ///
        /// Used only by VisualTreeHelper.

View on GitHub (pinned to 81131a70a4)