dotnet/wpf · error · ArgumentException
SR.TextRangeProvider_WrongTextRange
Error message
SR.TextRangeProvider_WrongTextRange
What it means
TextRangeAdaptor.ValidateAndThrow throws ArgumentException when the supplied ITextRangeProvider is either not a TextRangeAdaptor instance or belongs to a different TextContainer than this adaptor. UI Automation range APIs require ranges that live in the same text container they operate on.
Solutions
- Verify the range was obtained from the same control's TextPattern/TextRangeProvider as the one the method is invoked on; re-acquire it via pattern.DocumentRange or the correct provider if not.
- Before use, cast to TextRangeAdaptor and compare the underlying TextContainer, mirroring the guard in ValidateAndThrow.
- Stop caching TextRangeProviders across control instances; fetch ranges per-target control at call time.
- If interoperating with non-WPF providers, translate the range into the target container rather than passing it directly.
Example fix
// before: applying a cached range from another control
var range = otherTextPattern.DocumentRange;
targetAdaptor.FindText("query", /* searchBackward */ false, /* ignoreCase */ true, ref range); // throws
// after: use a range that belongs to the same container
var ownPattern = (TextPattern)targetElement.GetCurrentValue(TextPattern.Pattern);
var range = ownPattern.DocumentRange;
targetAdaptor.FindText("query", false, true, ref range); // same container: OK Defensive patterns
Strategy: type-guard
Validate before calling
// before invoking a TextRangeAdaptor API with a foreign range: bool containerMatches = range is TextRangeAdaptor adapt && adapt != null; // full guard requires comparing containers as the library does: // adaptor._start.TextContainer == targetAdaptor._start.TextContainer
Type guard
static bool IsValidForTarget(ITextRangeProvider range, TextRangeAdaptor target)
=> range is TextRangeAdaptor adaptor && adaptor._start?.TextContainer == target._start.TextContainer; Try / catch
try
{
targetAdaptor.FindText("query", false, true, ref range);
}
catch (ArgumentException ex) when (ex.Message.Contains("range"))
{
range = ownPattern.DocumentRange; // re-acquire a range from the same container and retry
targetAdaptor.FindText("query", false, true, ref range);
} Prevention
- Always obtain ranges from the TextPattern of the same element the adaptor belongs to.
- Do not cache TextRangeProviders across different controls or visual-tree rebuilds.
- Mirror the container check (range is TextRangeAdaptor && same TextContainer) before calling the API.
- Translate foreign-provider ranges into the target container rather than passing them through.
When it happens
Trigger: Calling a TextRangeAdaptor method (e.g. FindText, Select, CompareTo, Clone-and-modify patterns) passing an ITextRangeProvider that came from a different control's TextPattern or from a non-WPF provider (null after the 'as' cast), so rangeAdaptor is null or its _start.TextContainer differs from the current _start.TextContainer.
Common situations: Mixing ranges across two TextBox/TextBlock/RichTextBox instances in UIA automation code; caching a TextRangeProvider from one control and applying it to another after the visual tree changed; passing a foreign/provider range (e.g. from a mock or another framework) into a WPF TextPattern operation.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- SR.PropertyNotSupported
- SR.TextProvider_InvalidPoint
- ArgumentOutOfRangeException
- ArgumentOutOfRangeException (timeout was Duration.Automatic)
- Collection_BadRank
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9d878580125f0af1.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextRangeAdaptor.cs:510
//-------------------------------------------------------------------
//
// Private Methods
//
//-------------------------------------------------------------------
#region Private Methods
/// <summary>
/// Verifies that the given range points to the same text container as this one.
/// </summary>
/// <returns>The validated range casted to TextRangeAdaptor</returns>
private TextRangeAdaptor ValidateAndThrow(ITextRangeProvider range)
{
TextRangeAdaptor rangeAdaptor = range as TextRangeAdaptor;
if (rangeAdaptor == null || rangeAdaptor._start.TextContainer != _start.TextContainer)
{
throw new ArgumentException(SR.TextRangeProvider_WrongTextRange);
}
return rangeAdaptor;
}
/// <summary>
/// Expands the range to an integral number of enclosing units. If the range is already an
/// integral number of the specified units then it remains unchanged.
/// </summary>
private void ExpandToEnclosingUnit(TextUnit unit, bool expandStart, bool expandEnd)
{
ITextView textView;
switch (unit)
{
case TextUnit.Character:
if (expandStart && !TextPointerBase.IsAtInsertionPosition(_start))
{
TextPointerBase.MoveToNextInsertionPosition(_start, LogicalDirection.Backward);
}View on GitHub (pinned to 81131a70a4)