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

  1. Pass the startNode that actually contains or precedes the selection (e.g. the node resolved from the same DocumentPageView).
  2. Re-resolve the anchor/selection against the current document before generating locator parts.
  3. 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

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


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)