dotnet/wpf · error · ArgumentOutOfRangeException

Argument out of range (start not contained in view)

Error message

Argument out of range (start not contained in view)

What it means

TextDocumentView.GetGlyphRuns validates that both the start and end positions fall within the view's laid-out text range. This error means the caller passed a start ITextPointer that is valid for the text container but lies outside the region currently represented by this view. The view only exposes geometry for text it has actually laid out.

Solutions

  1. Re-obtain start/end pointers from the current view (e.g. via TextViewBase methods or TextPointer from a fresh layout pass) instead of reusing cached ones
  2. Check the view's range before calling: create/validate a TextSpan from the view's own start/end and ensure the pointers are inside it
  3. Force a fresh layout (EnsureLayout / update the view) so the pointer's position is materialized before querying glyphs
  4. Catch ArgumentOutOfRangeException around the call and re-resolve the position against the current view

Example fix

// before
var glyphs = view.GetGlyphRuns(cachedStart, cachedEnd);
// after
if (view.Contains(cachedStart) && view.Contains(cachedEnd))
{
    var glyphs = view.GetGlyphRuns(cachedStart, cachedEnd);
}
else
{
    var start = view.GetTextPositionFromPoint(point, snapToText: true);
    var end = view.DocumentEnd;
    var glyphs = view.GetGlyphRuns(start, end);
}
Defensive patterns

Strategy: validation

Validate before calling

// WPF C#
if (!view.Contains(start)) throw new InvalidOperationException("start outside view range");
// or guard silently:
if (view.Contains(start) && view.Contains(end)) { /* call GetGlyphRuns */ }

Type guard

bool IsInView(TextDocumentView view, ITextPointer p) => view != null && view.Contains(p);

Try / catch

try { var runs = view.GetGlyphRuns(start, end); }
catch (ArgumentOutOfRangeException) { start = view.GetTextPositionFromPoint(fallbackPoint, true); /* re-resolve and retry or skip */ }

Prevention

When it happens

Trigger: Calling GetGlyphRuns with a start pointer pointing at text that was never laid out in this view (e.g. content in a collapsed region, another column, or text outside the visible document range). The start passes VerifyPosition against the container but fails ContainsCore(start).

Common situations: Hit while writing custom renderers or hit-testing helpers against TextBlock/FlowDocument views after the document shrinks (deleting text the pointer referenced), or caching pointers across layout invalidations and reusing them after the view re-ranged.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/TextDocumentView.cs:367

        /// <summary>
        /// <see cref="ITextView.GetGlyphRuns"/>
        /// </summary>
        internal override ReadOnlyCollection<GlyphRun> GetGlyphRuns(ITextPointer start, ITextPointer end)
        {
            List<GlyphRun> glyphRuns = new List<GlyphRun>();

            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid)
            {
                throw new InvalidOperationException(SR.TextViewInvalidLayout);
            }
            ValidationHelper.VerifyPosition(_textContainer, start, nameof(start));
            ValidationHelper.VerifyPosition(_textContainer, end, nameof(end));
            ValidationHelper.VerifyPositionPair(start, end);
            if (!ContainsCore(start))
            {
                throw new ArgumentOutOfRangeException(nameof(start));
            }
            if (!ContainsCore(end))
            {
                throw new ArgumentOutOfRangeException(nameof(end));
            }

            GetGlyphRuns(glyphRuns, start, end, Columns, FloatingElements);

            return new ReadOnlyCollection<GlyphRun>(glyphRuns);
        }

        /// <summary>
        /// <see cref="ITextView.Contains"/>
        /// </summary>
        internal override bool Contains(ITextPointer position)
        {
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid)

View on GitHub (pinned to 81131a70a4)