dotnet/wpf · error · InvalidOperationException

SR.Format(SR.NotInThisTree, "position")

Error message

SR.Format(SR.NotInThisTree, "position")

What it means

TextContainer.ValidateSetValue verifies that the supplied TextPointer belongs to this text tree before any set-value operation; if position.TextContainer != this it throws InvalidOperationException(NotInThisTree, "position"), because positions are only valid within their owning container.

Solutions

  1. Obtain a fresh TextPointer from the target TextContainer (e.g. targetDocument.ContentStart) instead of reusing one from another document
  2. Verify position.TextContainer == targetContainer before the call
  3. Re-map the position: read the offset/text in the source container and recreate the pointer in the target

Example fix

// before
targetContainer.ValidateSetValue(pointerFromOtherDoc); // wrong tree
// after
var local = targetContainer.CreatePointerAtOffset(computeOffset(pointerFromOtherDoc), LogicalDirection.Forward);
targetContainer.ValidateSetValue(local);
Defensive patterns

Strategy: validation

Validate before calling

bool sameTree = position.TextContainer == targetContainer;

Type guard

static bool IsInTree(TextPointer p, TextContainer t) => p != null && p.TextContainer == t;

Try / catch

try { container.ValidateSetValue(position); } catch (InvalidOperationException) when (!sameTree) { position = container.CreatePointerAtOffset(offset, position.LogicalDirection); }

Prevention

When it happens

Trigger: Passing a TextPointer obtained from a different FlowDocument/TextContainer into an operation on another TextContainer (e.g. setting a property value via a position from another document).

Common situations: Copy/paste or cross-document editing code reusing TextPointer instances across two RichTextBox/FlowDocument instances; caching a position after the document was swapped.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextContainer.cs:3215

            valuesEnumerator.Reset();
            while (valuesEnumerator.MoveNext())
            {
                properties[count++] = valuesEnumerator.Current.Property;
            }

            return properties;
        }

        #region ValidateXXXHelpers

        // Validation for SetValue.
        private void ValidateSetValue(TextPointer position)
        {
            TextElement element;

            if (position.TextContainer != this)
            {
                throw new InvalidOperationException(SR.Format(SR.NotInThisTree, "position"));
            }

            position.SyncToTreeGeneration();

            element = position.Parent as TextElement;
            if (element == null)
            {
                throw new InvalidOperationException(SR.NoElement);
            }
        }

        #endregion ValidateXXXHelpers

        // Verifies the TextContainer symbol count is in synch with the TextTreeText
        // character count.
        private void AssertTreeAndTextSize()
        {
            if (Invariant.Strict)

View on GitHub (pinned to 81131a70a4)