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
- Handle TextContainer.ContentChanged (after the change completes) instead of Changing.
- If you must react during Changing, post work with Dispatcher.BeginInvoke so it runs after the change block closes.
- 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
- Use TextContainer.ContentChanged instead of Changing to react to edits
- Never call TextFlow APIs from within a BeginChange/EndChange block
- Queue post-change work on the dispatcher
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
- SR.TextContainerChangingReentrancyInvalid
- SR.TextContainerChangingReentrancyInvalid
- Processing is disabled while the Dispatcher is in this…
- SR.ArrangeReentrancyInvalid
- SR.ArrangeReentrancyInvalid
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)