dotnet/wpf · error · ArgumentException
SR.Format(SR.NotInAssociatedTree, "textPointer")
Error message
SR.Format(SR.NotInAssociatedTree, "textPointer")
What it means
TextAnchor.Contains verifies that the given ITextPointer belongs to the same TextContainer as the anchor's Start pointer before comparing positions. WPF throws this ArgumentException when a pointer from a different document/tree is passed, because positional comparison across containers is meaningless. It is an API-contract check protecting the annotations framework from cross-tree corruption.
Solutions
- Pass a pointer obtained from the same TextContainer as the anchor (anchor.Start.TextContainer).
- If you have a pointer from another tree, resolve it back to a container-agnostic offset (or TextMap/annotation locator) and re-create a pointer inside the target container.
- Guard the call: check textPointer.TextContainer == anchor.Start.TextContainer before calling Contains.
Example fix
// before
bool hit = anchor.Contains(pointerFromOtherDocument);
// after
if (pointer.TextContainer == anchor.Start.TextContainer)
{
bool hit = anchor.Contains(pointer);
} Defensive patterns
Strategy: validation
Validate before calling
if (pointer == null || pointer.TextContainer != anchor.Start.TextContainer)
throw new ArgumentException("textPointer belongs to a different TextContainer"); Type guard
bool IsInAnchorTree(ITextPointer p, TextAnchor a) => p != null && p.TextContainer == a.Start.TextContainer;
Prevention
- Always obtain pointers from the same document/container the anchor was created against.
- Do not cache ITextPointer instances across document lifetime changes.
- Centralize pointer creation in one helper that receives the TextContainer.
When it happens
Trigger: Calling TextAnchor.Contains(textPointer) with an ITextPointer whose TextContainer property differs from this.Start.TextContainer — e.g. a pointer obtained from a second FlowDocument/TextBox while the anchor belongs to the first.
Common situations: Annotation code that stores TextRange/anchor data across multiple documents or recreates a document instance and mixes old pointers with a new anchor; copy-paste logic that carries pointers between containers.
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
- SR.AnnotationAdorner_NotUIElement
- SR.InvalidValueSpecified
- SR.TypeNameMustBeSpecified
- " }} " element found. Expected fixed page element ( }} ).
- ' ' ContentType is not valid.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/cd6d25bd547f6ba1.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/TextAnchor.cs:105
//
// Public Methods
//
//------------------------------------------------------
#region Public Methods
/// <summary>
/// Determines if the text pointer is contained by one of the
/// anchor's TextSegment.s
/// </summary>
/// <param name="textPointer">text pointer to test</param>
internal bool Contains(ITextPointer textPointer)
{
ArgumentNullException.ThrowIfNull(textPointer);
if (textPointer.TextContainer != this.Start.TextContainer)
{
throw new ArgumentException(SR.Format(SR.NotInAssociatedTree, "textPointer"));
}
// Correct position normalization on range boundary so that
// our test would not depend on what side of formatting tags
// pointer is located.
if (textPointer.CompareTo(this.Start) < 0)
{
textPointer = textPointer.GetInsertionPosition(LogicalDirection.Forward);
}
else if (textPointer.CompareTo(this.End) > 0)
{
textPointer = textPointer.GetInsertionPosition(LogicalDirection.Backward);
}
// Check if at least one segment contains this position.
for (int i = 0; i < _segments.Count; i++)
{
if (_segments[i].Contains(textPointer))View on GitHub (pinned to 81131a70a4)