dotnet/wpf · error · InvalidOperationException

SR.NoScopingElement (This TextNavigator)

Error message

SR.NoScopingElement (This TextNavigator)

What it means

This TextPointer method (an internal move/validate helper, e.g. MoveToContentBoundary's validation) requires an element node scoping the pointer. After syncing to the tree generation, if the scoping node is neither a TextElement-derived node nor the tree root, it throws InvalidOperationException(SR.NoScopingElement, "This TextNavigator") because the pointer has no valid scoping element in the current tree.

Solutions

  1. Re-acquire the TextPointer from the current document (ContentStart/ContentEnd/selection) instead of reusing stale pointers.
  2. Check that the pointer's Parent is a TextElement before moving; if not, discard or re-create the pointer.
  3. Catch InvalidOperationException, re-derive the pointer, and retry the operation.

Example fix

// before
savedPointer.MoveToPosition(otherPointer, LogicalDirection.Forward);
// after
if (savedPointer.Parent is TextElement)
    savedPointer.MoveToPosition(otherPointer, LogicalDirection.Forward);
else
    savedPointer = richTextBox.Document.ContentStart;
Defensive patterns

Strategy: validation

Validate before calling

if (!(pointer.Parent is TextElement))
    pointer = document.ContentStart.GetInsertionPosition(LogicalDirection.Forward);

Type guard

static bool IsNavigatorUsable(TextPointer p) => p.Parent is TextElement || p.GetAdjacentElement(LogicalDirection.Forward) != null;

Try / catch

try { pointer.MoveToPosition(target, dir); }
catch (InvalidOperationException) { pointer = document.ContentStart; }

Prevention

When it happens

Trigger: Invoking the public TextPointer move/validation API on a pointer whose scoping node is no longer a TextElement (e.g. after the surrounding element was removed by an edit, or the pointer belongs to a stale/detached TextContainer generation).

Common situations: Holding a TextPointer across document restructure (blocks cleared/replaced) and then using it; pointers captured before asynchronous UI updates; using pointers from one RichTextBox's document against another.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/e10997e3279a69a8. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextPointer.cs:2640

            _tree.EmptyDeadPositionList();

            SyncToTreeGeneration();

            TextTreeNode scopingNode = GetScopingNode();
            elementNode = scopingNode as TextTreeTextElementNode;
            if (elementNode == null)
            {
                // if we're at the root of the tree, the pointer is
                // already at the element edge, and nothing more need be done.
                // This case can arise when a text tree contains only a
                // BlockUIContainer (and no text)
                if (scopingNode is TextTreeRootNode)
                {
                    return;
                }

                throw new InvalidOperationException(SR.Format(SR.NoScopingElement, "This TextNavigator"));
            }

            MoveToNode(_tree, elementNode, edge);
        }

        // <see cref="TextPointer.MoveToLineBoundary"/>
        int ITextPointer.MoveToLineBoundary(int count)
        {
            return MoveToLineBoundary(count);
        }

        // <see cref="TextPointer.GetCharacterRect"/>
        Rect ITextPointer.GetCharacterRect(LogicalDirection direction)
        {
            return GetCharacterRect(direction);
        }

        bool ITextPointer.MoveToInsertionPosition(LogicalDirection direction)

View on GitHub (pinned to 81131a70a4)