dotnet/wpf · error · ArgumentException
SR.InvalidStartNodeForTextSelection
Error message
SR.InvalidStartNodeForTextSelection
What it means
GenerateLocatorParts checks that the startNode's text span actually overlaps the selection: if the node's element start lies after the selection end, the node cannot correspond to the selection and this ArgumentException is thrown.
Solutions
- Pass the startNode that actually contains or precedes the selection (e.g. the node resolved from the same DocumentPageView).
- Re-resolve the anchor/selection against the current document before generating locator parts.
- Catch ArgumentException and recompute the start node via the selection processor.
Example fix
// before
var part = processor.GenerateLocatorParts(selection, staleStartNode, pageView);
// after
var correctNode = processor.GetSelectedNodes(selection).FirstOrDefault();
var part = correctNode != null
? processor.GenerateLocatorParts(selection, correctNode, pageView)
: null; Defensive patterns
Strategy: validation
Validate before calling
bool overlaps = elementStart.CompareTo(selectionEnd) <= 0;
if (!overlaps) throw new InvalidOperationException("startNode is after selection end"); Try / catch
try { part = processor.GenerateLocatorParts(selection, startNode, pageView); }
catch (ArgumentException ex) when (ex.Message.Contains("startNode")) { part = null; /* skip node */ } Prevention
- Always derive startNode from the same selection/page view being anchored.
- Do not cache TextNodes across re-layout or document edits.
- Re-resolve anchors after any content change before generating locator parts.
When it happens
Trigger: Calling GenerateLocatorParts(selection, startNode) where startNode is a DependencyObject positioned entirely after the selection in document order — typically a wrong or stale node (e.g. node from a different document/page or a mismatched DocumentPageView).
Common situations: Caching TextNodes across re-layout or document edits; passing the wrong page's start node when generating locators per page view; anchors whose offsets are stale after content changes.
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
- SR.AnnotationServiceNotEnabled
- SR.Format(SR.IncorrectLocatorPartType, " : ")
- SR.Format(SR.InvalidLocatorPart…
- SR.ParameterMustBeLogicalNode
- SR.WrongSelectionType
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/901d079a60c51986.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Anchoring/TextSelectionProcessor.cs:145
ArgumentNullException.ThrowIfNull(selection);
ITextPointer start;
ITextPointer end;
IList<TextSegment> textSegments = null;
TextSelectionHelper.CheckSelection(selection, out start, out end, out textSegments);
if (!(start is TextPointer))
throw new ArgumentException(SR.WrongSelectionType, nameof(selection));
ITextPointer elementStart;
ITextPointer elementEnd;
// If we can't get the start/end of the node then we can't generate a locator part
if (!GetNodesStartAndEnd(startNode, out elementStart, out elementEnd))
return null;
if (elementStart.CompareTo(end) > 0)
throw new ArgumentException(SR.InvalidStartNodeForTextSelection, nameof(startNode));
if (elementEnd.CompareTo(start) < 0)
throw new ArgumentException(SR.InvalidStartNodeForTextSelection, nameof(startNode));
ContentLocatorPart part = new ContentLocatorPart(CharacterRangeElementName);
int startOffset = 0;
int endOffset = 0;
for (int i = 0; i < textSegments.Count; i++)
{
GetTextSegmentValues(textSegments[i], elementStart, elementEnd, out startOffset, out endOffset);
part.NameValuePairs.Add(SegmentAttribute + i.ToString(NumberFormatInfo.InvariantInfo), startOffset.ToString(NumberFormatInfo.InvariantInfo) + TextSelectionProcessor.Separator + endOffset.ToString(NumberFormatInfo.InvariantInfo));
}
part.NameValuePairs.Add(CountAttribute, textSegments.Count.ToString(NumberFormatInfo.InvariantInfo));
List<ContentLocatorPart> res = new List<ContentLocatorPart>(1);View on GitHub (pinned to 81131a70a4)