dotnet/wpf · error · ArgumentOutOfRangeException

SR.Visual_ArgumentOutOfRange

Error message

SR.Visual_ArgumentOutOfRange

What it means

AnnotationAdorner hosts exactly one visual child — the wrapped annotation component. GetVisualChild overrides the Visual contract and throws ArgumentOutOfRangeException when index is not 0 or when the component is null. This is a defensive check ensuring WPF's visual-tree enumeration stays consistent with VisualChildrenCount.

Solutions

  1. Never mutate the visual tree during layout passes or inside GetVisualChild/VisualChildrenCount overrides.
  2. Ensure VisualChildrenCount returns 1 exactly when _annotationComponent != null and 0 otherwise.
  3. Keep the wrapped component alive for the adorner's full lifetime; don't null it out while attached.
  4. If hit inside framework code, capture a WPF layout/visual-tree dump and report; work around by rebuilding the adorner.

Example fix

// before
protected override int VisualChildrenCount => _annotationComponent == null ? 0 : 2; // inconsistent
// after
protected override int VisualChildrenCount => _annotationComponent == null ? 0 : 1;
Defensive patterns

Strategy: validation

Validate before calling

int count = adorner.VisualChildrenCount;
bool safeIndex = count == 1; // only index 0 is valid when a component is present

Type guard

bool CanGetChild(AnnotationAdorner a, int i) => i == 0 && a.VisualChildrenCount == 1;

Try / catch

try { var child = adorner.GetVisualChild(i); }
catch (ArgumentOutOfRangeException) { /* index outside the single-child contract */ }

Prevention

When it happens

Trigger: WPF layout/visual enumeration calls GetVisualChild with an index outside [0, VisualChildrenCount); or enumeration races the constructor before _annotationComponent is assigned. Rarely triggered directly by user code — usually via corrupted visual bookkeeping.

Common situations: Custom code that overrides VisualChildrenCount inconsistently with GetVisualChild; deleting the child component while the visual tree is still being enumerated (modification during the GetVisualChild virtual call, which the framework forbids).

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Component/AnnotationAdorner.cs:104

        #endregion Public Methods

        #region Protected Methods

        /// <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: 
        ///       During this virtual call it is not valid to modify the Visual tree. 
        /// </summary>
        protected override Visual GetVisualChild(int index)
        {
            if (index != 0 || _annotationComponent == null)
            {
                throw new ArgumentOutOfRangeException(nameof(index), index, SR.Visual_ArgumentOutOfRange);
            }

            return (UIElement)_annotationComponent;
        }

        /// <summary>
        ///  Derived classes override this property to enable the Visual code to enumerate 
        ///  the Visual children. Derived classes need to return the number of children
        ///  from this method.
        ///
        ///    By default a Visual does not have any children.
        ///
        ///  Remark: During this virtual method the Visual tree must not be modified.
        /// </summary>        
        protected override int VisualChildrenCount
        {
            get { return _annotationComponent != null ? 1 : 0; }
        }

View on GitHub (pinned to 81131a70a4)