dotnet/wpf · error · InvalidOperationException

SR.TextContainerChangingReentrancyInvalid

Error message

SR.TextContainerChangingReentrancyInvalid

What it means

VerifyReentrancy also rejects calls while a TextContainer change is in progress: if Flags.ContentChangeInProgress is set, it throws InvalidOperationException(SR.TextContainerChangingReentrancyInvalid). This prevents mutating or querying the text layout while the TextTree is inside a change block (e.g. from a TextContainer.Changing handler).

Solutions

  1. Handle TextContainer.ContentChanged (after the change completes) instead of Changing.
  2. If you must react during Changing, post work with Dispatcher.BeginInvoke so it runs after the change block closes.
  3. Ensure you do not call TextFlow APIs from within your own BeginChange/EndChange scopes that are nested inside layout.

Example fix

// before
textContainer.Changing += (s, e) => Reformat(_textFlow);
// after
textContainer.ContentChanged += (s, e) => Dispatcher.BeginInvoke(() => Reformat(_textFlow));
Defensive patterns

Strategy: validation

Validate before calling

// Prefer: only react after the change completes.
if (!isInsideContentChangeScope) DoTextFlowWork(); // track your own BeginChange scopes

Try / catch

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

Prevention

When it happens

Trigger: Calling a public TextFlow method from a TextContainer.Changing event handler, from within a BeginChange/EndChange scope on the TextContainer, or from any callback invoked synchronously during content change.

Common situations: Developers hooking TextContainer.Changing to update UI or reformat text; code that reacts to document edits immediately instead of deferring to the ContentChanged event.

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

Appendix: source

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

        // ------------------------------------------------------------------
        // 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()
        {
            Rect visibleRect = new Rect(0, 0, RenderSize.Width, RenderSize.Height);

            Visual visual = VisualTreeHelper.GetParent(this) as Visual;

            while(visual != null && visibleRect != Rect.Empty)
            {                
                if(VisualTreeHelper.GetClip(visual) != null)
                {
                    GeneralTransform transform = this.TransformToAncestor(visual).Inverse;
                    

View on GitHub (pinned to 81131a70a4)