dotnet/wpf · error · InvalidOperationException

SR.TextPointer_CannotInsertTextElementBecauseItBelongsToAnot…

Error message

SR.TextPointer_CannotInsertTextElementBecauseItBelongsToAnotherTree

What it means

TextPointer.InsertTextElement validates, via ValidationHelper.ValidateChild and an explicit Parent check, that the TextElement being inserted is new (unparented). If textElement.Parent != null — the element already belongs to another tree (or another position in this one) — it throws InvalidOperationException(SR.TextPointer_CannotInsertTextElementBecauseItBelongsToAnotherTree). A TextElement can live in exactly one tree.

Solutions

  1. Ensure the element is detached first (remove it from its current parent/collection) before inserting.
  2. Create a new element instance (or deep copy) rather than reusing the parented one.
  3. If moving between documents, use TextRange/clipboard-based copy APIs or manually reparent: sourceCollection.Remove(element) then target InsertTextElement.

Example fix

// before
targetPointer.InsertTextElement(run); // run.Parent != null
// after
if (run.Parent is TextElementCollection<Run> col) col.Remove(run);
((IAddChild)run.Parent)?. // or:
run.RepositionWithContent(null); // detach, then
targetPointer.InsertTextElement(run);
Defensive patterns

Strategy: validation

Validate before calling

if (textElement.Parent != null)
{
    // detach first
    if (textElement.Parent is TextElement p) /* remove from p */;
    else if (textElement.Parent is IAddChild) /* remove from container collection */;
}

Type guard

bool CanInsert(TextElement e) => e != null && e.Parent == null;

Try / catch

try { pointer.InsertTextElement(element); }
catch (InvalidOperationException ex) when (ex.Message.Contains("another tree")) { /* clone or detach and retry */ }

Prevention

When it happens

Trigger: Calling InsertTextElement (via TextPointer.Insert, TextElementCollection.Add/Insert, InsertEmbeddedObject/UIElement wrappers, or InsertLineBreak-style helpers) with an element instance that is already parented — e.g. re-inserting a Run/UIElement that was removed from one document into another, or moving an element without detaching it.

Common situations: Moving a Run or embedded UIElement from one FlowDocument/RichTextBox to another; caching element instances and reusing them after the document was reloaded; cloning documents by reusing child elements instead of deep-copying.

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/60d99656419155be. Report an issue: GitHub.

Appendix: source

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

        /// Throws ArgumentException is textElement is not valid
        /// according to flow schema.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Throws InvalidOperationException if textElement cannot be inserted
        /// at this position because it belongs to another tree.
        /// </exception>
        internal void InsertTextElement(TextElement textElement)
        {
            Invariant.Assert(textElement != null);

            _tree.EmptyDeadPositionList();
            SyncToTreeGeneration();

            ValidationHelper.ValidateChild(this, textElement, nameof(textElement));

            if (textElement.Parent != null)
            {
                throw new InvalidOperationException(SR.TextPointer_CannotInsertTextElementBecauseItBelongsToAnotherTree);
            }
            textElement.RepositionWithContent(this);
        }

        /// <summary>
        /// Insert a paragraph break at this position by splitting all elements upto its paragraph ancestor.
        /// </summary>
        /// <returns>
        /// When this position has a paragraph parent, this method returns a
        /// normalized position in the beginning of a second paragraph.
        ///
        /// Otherwise, if the position is not parented by a paragraph
        /// (for special insertion positions such as table row end, BlockUIContainer boundaries, etc),
        /// this method creates a paragraph by using rules of EnsureInsertionPosition()
        /// and returns a normalized position at the start of the paragraph created.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// Throws InvalidOperationException when this position has a non-splittable ancestor such as Hyperlink,

View on GitHub (pinned to 81131a70a4)