{"record":{"id":"9d878580125f0af1","repo":"dotnet/wpf","slug":"sr-textrangeprovider-wrongtextrange","errorCode":null,"errorMessage":"SR.TextRangeProvider_WrongTextRange","messagePattern":"SR\\.TextRangeProvider_WrongTextRange","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextRangeAdaptor.cs","lineNumber":510,"sourceCode":"\n        //-------------------------------------------------------------------\n        //\n        //  Private Methods\n        //\n        //-------------------------------------------------------------------\n\n        #region Private Methods\n\n        /// <summary>\n        /// Verifies that the given range points to the same text container as this one.\n        /// </summary>\n        /// <returns>The validated range casted to TextRangeAdaptor</returns>\n        private TextRangeAdaptor ValidateAndThrow(ITextRangeProvider range)\n        {\n            TextRangeAdaptor rangeAdaptor = range as TextRangeAdaptor;\n            if (rangeAdaptor == null || rangeAdaptor._start.TextContainer != _start.TextContainer)\n            {\n                throw new ArgumentException(SR.TextRangeProvider_WrongTextRange);\n            }\n            return rangeAdaptor;\n        }\n\n        /// <summary>\n        /// Expands the range to an integral number of enclosing units.  If the range is already an\n        /// integral number of the specified units then it remains unchanged.\n        /// </summary>\n        private void ExpandToEnclosingUnit(TextUnit unit, bool expandStart, bool expandEnd)\n        {\n            ITextView textView;\n            switch (unit)\n            {\n                case TextUnit.Character:\n                    if (expandStart && !TextPointerBase.IsAtInsertionPosition(_start))\n                    {\n                        TextPointerBase.MoveToNextInsertionPosition(_start, LogicalDirection.Backward);\n                    }","sourceCodeStart":492,"sourceCodeEnd":528,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextRangeAdaptor.cs#L492-L528","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: applying a cached range from another control\nvar range = otherTextPattern.DocumentRange;\ntargetAdaptor.FindText(\"query\", /* searchBackward */ false, /* ignoreCase */ true, ref range); // throws\n\n// after: use a range that belongs to the same container\nvar ownPattern = (TextPattern)targetElement.GetCurrentValue(TextPattern.Pattern);\nvar range = ownPattern.DocumentRange;\ntargetAdaptor.FindText(\"query\", false, true, ref range); // same container: OK","handlingStrategy":"type-guard","validationCode":"// before invoking a TextRangeAdaptor API with a foreign range:\nbool containerMatches = range is TextRangeAdaptor adapt && adapt != null;\n// full guard requires comparing containers as the library does:\n// adaptor._start.TextContainer == targetAdaptor._start.TextContainer","typeGuard":"static bool IsValidForTarget(ITextRangeProvider range, TextRangeAdaptor target)\n    => range is TextRangeAdaptor adaptor && adaptor._start?.TextContainer == target._start.TextContainer;","tryCatchPattern":"try\n{\n    targetAdaptor.FindText(\"query\", false, true, ref range);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"range\"))\n{\n    range = ownPattern.DocumentRange; // re-acquire a range from the same container and retry\n    targetAdaptor.FindText(\"query\", false, true, ref range);\n}","preventionTips":["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."],"tags":["wpf","ui-automation","textrange","argument-exception"],"backgroundTag":"incompatible-source-type","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}