dotnet/wpf · error · InvalidOperationException

SR.MeasureReentrancyInvalid

Error message

SR.MeasureReentrancyInvalid

What it means

TextFlow guards against reentrancy during its measure pass. VerifyReentrancy checks the MeasureInProgress flag and throws InvalidOperationException(SR.MeasureReentrancyInvalid) if any public TextFlow method is invoked while measure is running. Text layout must not be queried or mutated from inside measure.

Solutions

  1. Move the TextFlow call out of the measure path — defer with Dispatcher.BeginInvoke or perform it after layout completes.
  2. Cache the values you need before measure starts instead of querying TextFlow during measure.
  3. If responding to a content-changed event, defer the response until the ContentChange scope (and measure) finishes.

Example fix

// before
protected override Size MeasureOverride(Size constraint) {
    var size = _textFlow.CalculateElementSize(constraint);
    var r = _textFlow.GetRectangles(_element); // reentrancy
    return size;
}
// after
protected override Size MeasureOverride(Size constraint) {
    var size = _textFlow.CalculateElementSize(constraint);
    Dispatcher.BeginInvoke(() => RenderRectangles(_textFlow.GetRectangles(_element)));
    return size;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Cannot pre-check private flags; instead restructure so TextFlow is not called during MeasureOverride.

Try / catch

try { DoTextFlowWork(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("measure")) { Dispatcher.BeginInvoke(DoTextFlowWork); }

Prevention

When it happens

Trigger: Calling a public TextFlow method (e.g. formatting, TextContainer changes, position queries) from within MeasureOverride of a TextFlow-driven control, or from a layout event/callback raised synchronously during measure.

Common situations: Custom text host controls that query text positions inside OnMeasure/MeasureOverride; event handlers (e.g. TextContainer change handlers) that trigger re-layout or formatting calls while measure is already in progress.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextFlow.cs:1510

        {
            // One of UIElement children has been changed. Need to 
            // notify NameTable about the change and remeasure content.
            // Treat this notification as OnChildUIElementChanged.
            UIElement uiChild = source as UIElement;
            if (uiChild != null)
            {
                OnChildUIElementChanged(uiChild);
            }
        }

        // ------------------------------------------------------------------
        // Ensures none of our methods can be called during measure/arrange/content change.
        // ------------------------------------------------------------------
        private void VerifyReentrancy()
        {
            if(CheckFlags(Flags.MeasureInProgress))
            {
                throw new InvalidOperationException(SR.MeasureReentrancyInvalid);
            }

            if(CheckFlags(Flags.ArrangeInProgress))
            {
                throw new InvalidOperationException(SR.ArrangeReentrancyInvalid);
            }

            if(CheckFlags(Flags.ContentChangeInProgress))
            {
                throw new InvalidOperationException(SR.TextContainerChangingReentrancyInvalid);
            }
        }

        // ------------------------------------------------------------------
        /// CalculateViewportRect - Called to calculate the visible rect for this element
        // ------------------------------------------------------------------
        private Rect CalculateViewportRect()
        {

View on GitHub (pinned to 81131a70a4)