dotnet/wpf · error · InvalidOperationException

SR.Format(SR.RichEditTextPatternHasNoChildren…

Error message

SR.Format(SR.RichEditTextPatternHasNoChildren, GetType().FullName)

What it means

The rich edit control's ITextProvider exposes one whole-document text range and no child elements (hyperlinks/embedded objects are not exposed as children). RangeFromChild is therefore meaningless for this element and unconditionally throws InvalidOperationException(SR.RichEditTextPatternHasNoChildren, GetType().FullName), naming the concrete proxy type in the message.

Solutions

  1. Use RangeFromPoint or DocumentRange / text-unit methods (Move, FindText) instead of RangeFromChild on rich edits
  2. Guard: only call RangeFromChild for providers that actually expose children; check the element's supported pattern/control type first
  3. Restructure automation to search text via FindText on the document range rather than child traversal

Example fix

// before
var range = textPattern.RangeFromChild(childElement); // always throws for RichEdit
// after
if (isRichEdit)
    var range = textPattern.DocumentRange.FindText(searchText, false, false);
else
    var range = textPattern.RangeFromChild(childElement);
Defensive patterns

Strategy: fallback

Validate before calling

var range = textPattern is RichEditTextPattern ? null : childElement != null ? textPattern.RangeFromChild(childElement) : null;

Type guard

bool SupportsRangeFromChild(TextPattern tp) => !(tp.GetType().Name.Contains("RichEdit"));

Try / catch

try { range = textPattern.RangeFromChild(child); } catch (InvalidOperationException) { range = textPattern.DocumentRange.FindText(text, false, false); }

Prevention

When it happens

Trigger: Calling ITextProvider.RangeFromChild(childElement) on a WindowsRichEdit-based Text pattern with any childElement argument — the call can never succeed.

Common situations: Generic Text-pattern helper code that walks UIA elements by calling RangeFromChild for every parent element; passing hyperlink or embedded-object automation elements assuming they are children of the rich edit.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WindowsRichEdit.cs:260

            else
                return new ITextRangeProvider[] { new WindowsRichEditRange(range, this) };
        }

        ITextRangeProvider [] ITextProvider.GetVisibleRanges()
        {
            ITextRange range = GetVisibleRange();

            if (range == null)
                return Array.Empty<ITextRangeProvider>();
            else
                return new ITextRangeProvider[] { new WindowsRichEditRange(range, this) };
        }

        ITextRangeProvider ITextProvider.RangeFromChild(IRawElementProviderSimple childElement)
        {
            // we don't have any children so this call must be in error.
            // if we implement children for hyperlinks and embedded objects then we'll need to change this.
            throw new InvalidOperationException(SR.Format(SR.RichEditTextPatternHasNoChildren, GetType().FullName));
        }

        ITextRangeProvider ITextProvider.RangeFromPoint(Point screenLocation)
        {
            // we must have called EnsureTextDocument() before arriving here.
            Debug.Assert(_document != null);

            // TextPattern has verified that the point is inside our client area so we don't need to check for that.

            // get the degenerate range at the point
            // we're assuming ITextDocument::RangeFromPoint always returns a degenerate range
            ITextRange range = _document.RangeFromPoint((int)screenLocation.X, (int)screenLocation.Y);
            Debug.Assert(range.Start == range.End);

            // if you wanted to get the character under the point instead of the degenerate range nearest
            // the point, then you would add:

            //// if the point is within the character to the right then expand the degenerate range to

View on GitHub (pinned to 81131a70a4)