dotnet/wpf · error · ArgumentException

SR.TextProvider_InvalidChild

Error message

SR.TextProvider_InvalidChild

What it means

TextProviderWrapper.RangeFromChild wraps a peer's ITextRangeProvider.RangeFromChild call. It requires the childElement argument to be an ElementProxy (the wrapper's provider representation); any other IRawElementProviderSimple is rejected up front with ArgumentException and SR.TextProvider_InvalidChild before the call is dispatched to the peer's thread.

Solutions

  1. Only pass child elements obtained from the same provider's tree (e.g. via GetChildren or RangeFromChild of the same TextPattern).
  2. Null-check and verify the element's runtime ID / provider identity matches the target provider before calling RangeFromChild.
  3. Refresh child element references from the current provider after UI updates instead of reusing stale ones.
  4. In client code catch ArgumentException from RangeFromChild and fall back to re-discovering the child.

Example fix

// before
var child = otherPattern.GetSelection()[0]; // element from a different provider
var range = textPattern.RangeFromChild(child);
// after
var child = textPatternDocument.GetChildren()[0]; // child of the same provider
if (child != null)
{
    var range = textPattern.RangeFromChild(child);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (childElement == null) throw new ArgumentNullException(nameof(childElement));
if (childElement is not ElementProxy) throw new ArgumentException("childElement must come from the same provider", nameof(childElement));

Type guard

bool IsValidChild(IRawElementProviderSimple child) => child is ElementProxy;

Try / catch

try
{
    var range = textPattern.RangeFromChild(childElement);
}
catch (ArgumentException ex) when (ex.Message.Contains("childElement"))
{
    childElement = documentElement.FindFirst(TreeScope.Children, condition); // rediscover from same provider
}

Prevention

When it happens

Trigger: Calling ITextRangeProvider.RangeFromChild (via UIA TextPattern.RangeFromChild) with a child element that was not obtained from this provider — e.g. an element from another provider/tree, a null reference, or a hand-built IRawElementProviderSimple that is not the ElementProxy this wrapper expects.

Common situations: Passing elements discovered in a different UIA tree or from another control into RangeFromChild; caching child elements across provider rebuilds so the proxy identity no longer matches; test code constructing mock providers.

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/a9a0962d7e03faf6. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Automation/TextProviderWrapper.cs:56

        //------------------------------------------------------
 
        #region Interface ITextProvider

        public ITextRangeProvider [] GetSelection()
        {
            return (ITextRangeProvider [])ElementUtil.Invoke(_peer, new DispatcherOperationCallback(GetSelection), null);
        }

        public ITextRangeProvider [] GetVisibleRanges()
        {
            return (ITextRangeProvider[])ElementUtil.Invoke(_peer, new DispatcherOperationCallback(GetVisibleRanges), null);
        }

        public ITextRangeProvider RangeFromChild(IRawElementProviderSimple childElement)
        {
            if (!(childElement is ElementProxy))
            {
                throw new ArgumentException(SR.Format(SR.TextProvider_InvalidChild, "childElement"));
            }

            return (ITextRangeProvider)ElementUtil.Invoke(_peer, new DispatcherOperationCallback(RangeFromChild), childElement);
        }

        public ITextRangeProvider RangeFromPoint(Point screenLocation)
        {
            return (ITextRangeProvider)ElementUtil.Invoke(_peer, new DispatcherOperationCallback(RangeFromPoint), screenLocation);
        }

        public ITextRangeProvider DocumentRange 
        {
            get
            {
                return (ITextRangeProvider)ElementUtil.Invoke(_peer, new DispatcherOperationCallback(GetDocumentRange), null);
            }
        }

View on GitHub (pinned to 81131a70a4)