dotnet/wpf · error · ArgumentException

SR.StartNodeMustBeDocumentPageViewOrFixedPage

Error message

SR.StartNodeMustBeDocumentPageViewOrFixedPage

What it means

FixedTextSelectionProcessor.ResolveLocatorPart resolves a ContentLocatorPart into a TextAnchor for annotations on FixedDocument content. The method receives a DependencyObject 'startNode' that must be a DocumentPageView or FixedPage; otherwise it cannot anchor the text. This ArgumentException is thrown when the start node is neither of those types.

Solutions

  1. Pass the DocumentPageView (for FixedDocument) or FixedPage that actually hosts the annotated content as startNode.
  2. Verify the element type before calling: if (node is DocumentPageView || node is FixedPage) { ... }
  3. Ensure the annotations are targeting FixedDocument/DocumentSequence content, not Flow content (use TextSelectionProcessor for flow).

Example fix

// before
processor.ResolveLocatorPart(locatorPart, someVisual, out attachmentLevel);
// after
var pageView = VisualTreeHelperExt.FindDescendant<DocumentPageView>(someVisual);
processor.ResolveLocatorPart(locatorPart, pageView ?? throw new InvalidOperationException("No DocumentPageView in tree"), out attachmentLevel);
Defensive patterns

Strategy: validation

Validate before calling

if (startNode is not DocumentPageView and not FixedPage) throw new InvalidOperationException("startNode must be DocumentPageView or FixedPage");

Type guard

bool IsValidStartNode(DependencyObject n) => n is DocumentPageView or FixedPage;

Try / catch

try { processor.ResolveLocatorPart(part, node, out var level); } catch (ArgumentException ex) { /* log: bad start node */ }

Prevention

When it happens

Trigger: Calling ResolveLocatorPart with a locator part whose start node (DependencyObject) is a null docPage — i.e. the passed startNode is not a DocumentPageView or FixedPage (or its subtree failed to resolve to one).

Common situations: Passing the wrong visual (e.g. the FlowDocumentPageView, a ScrollViewer, or the AnnotationService host control) instead of the DocumentPageView that hosts fixed content; custom anchoring code that walks the visual tree and grabs an ancestor of the page view.

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/92af99b6a275c8dd. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Anchoring/FixedTextSelectionProcessor.cs:281

            else
            {
                // If we were passed a DPV because we are walking the visual tree,
                // extract the DocumentPage from it;  its TextView will be used to
                // turn coordinates into text positions
                DocumentPageView dpv = startNode as DocumentPageView;
                if (dpv != null)
                {
                    docPage = dpv.DocumentPage as FixedDocumentPage;
                    if (docPage == null)
                    {
                        docPage = dpv.DocumentPage as FixedDocumentSequenceDocumentPage;
                    }
                }
            }

            if (docPage == null)
            {
                throw new ArgumentException(SR.StartNodeMustBeDocumentPageViewOrFixedPage, nameof(startNode));
            }

            ArgumentNullException.ThrowIfNull(locatorPart);

            attachmentLevel = AttachmentLevel.Unresolved;

            ITextView tv = (ITextView)((IServiceProvider)docPage).GetService(typeof(ITextView));
            Debug.Assert(tv != null);

            ReadOnlyCollection<TextSegment> ts = tv.TextSegments;

            //check first if a TextRange can be generated
            if (ts == null || ts.Count <= 0)
                return null;

            TextAnchor resolvedAnchor = new TextAnchor();

            if (docPage != null)

View on GitHub (pinned to 81131a70a4)