dotnet/wpf · error · ArgumentException

SR.Format(SR.InDifferentTextContainers, "start", "end")

Error message

SR.Format(SR.InDifferentTextContainers, "start", "end")

What it means

The Span(TextPointer start, TextPointer end) constructor throws ArgumentException with SR.InDifferentTextContainers ("start" and "end" as parameter names) when the two TextPointers belong to different TextContainers (i.e. different documents/text stores). A Span must cover a range within a single text container, so positions from two different documents cannot define one.

Solutions

  1. Ensure both TextPointers come from the same document/container before constructing the Span.
  2. If ranges span documents, compute equivalent positions by offset (e.g. ContentStart.GetOffsetToPosition) in the target document instead.
  3. Guard with a check that start.TextContainer == end.TextContainer and throw a clearer domain error first.
  4. Catch ArgumentException and map it to a user-facing 'selection spans documents' message.

Example fix

// before
var span = new Span(doc1Start, doc2End);
// after
if (doc1Start.TextContainer != doc2End.TextContainer)
    throw new InvalidOperationException("start and end must belong to the same document.");
var span = new Span(doc1Start, doc1End);
Defensive patterns

Strategy: validation

Validate before calling

if (start == null || end == null) throw new ArgumentNullException(start == null ? nameof(start) : nameof(end));
if (start.TextContainer != end.TextContainer)
    throw new ArgumentException("start and end must belong to the same TextContainer.");

Type guard

static bool SameContainer(TextPointer a, TextPointer b) => a != null && b != null && a.TextContainer == b.TextContainer;

Try / catch

try { span = new Span(start, end); }
catch (ArgumentException ex) { throw new InvalidOperationException("Cannot create a range across two different documents.", ex); }

Prevention

When it happens

Trigger: new Span(startPointer, endPointer) where startPointer and endPointer come from two different FlowDocument/TextEditor/TextContainer instances (start.TextContainer != end.TextContainer).

Common situations: Copying TextPointers between two RichTextBox/FlowDocument instances and assuming they are interchangeable; caching a pointer from a document that was reloaded so the new pointer pairs with an old-document pointer; diffing or copying ranges across documents.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Span.cs:92

        /// Creates a new Span instance covering existing content.
        /// </summary>
        /// <param name="start">
        /// Start position of the new Span.
        /// </param>
        /// <param name="end">
        /// End position of the new Span.
        /// </param>
        /// <remarks>
        /// start and end must both be parented by the same Paragraph, otherwise
        /// the method will raise an ArgumentException.
        /// </remarks>
        public Span(TextPointer start, TextPointer end)
        {
            ArgumentNullException.ThrowIfNull(start);
            ArgumentNullException.ThrowIfNull(end);
            if (start.TextContainer != end.TextContainer)
            {
                throw new ArgumentException(SR.Format(SR.InDifferentTextContainers, "start", "end"));
            }
            if (start.CompareTo(end) > 0)
            {
                throw new ArgumentException(SR.Format(SR.BadTextPositionOrder, "start", "end"));
            }

            start.TextContainer.BeginChange();
            try
            {
                start = TextRangeEditTables.EnsureInsertionPosition(start);
                Invariant.Assert(start.Parent is Run);
                end = TextRangeEditTables.EnsureInsertionPosition(end);
                Invariant.Assert(end.Parent is Run);

                if (start.Paragraph != end.Paragraph)
                {
                    throw new ArgumentException(SR.Format(SR.InDifferentParagraphs, "start", "end"));
                }

View on GitHub (pinned to 81131a70a4)