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
- Never mutate the visual tree during layout passes or inside GetVisualChild/VisualChildrenCount overrides.
- Ensure VisualChildrenCount returns 1 exactly when _annotationComponent != null and 0 otherwise.
- Keep the wrapped component alive for the adorner's full lifetime; don't null it out while attached.
- 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
- Keep VisualChildrenCount and GetVisualChild consistent in custom adorners
- Never modify the visual tree during layout/enumeration passes
- Hold the wrapped component for the adorner's full lifetime
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
- Specified index is out of range or child at index is null…
- Specified index is out of range or child at index is null…
- SR.Format(SR.Invalid_IInputElement, doTarget.GetType())
- SR.Visual_ArgumentOutOfRange
- SR.Visual_ArgumentOutOfRange
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)