dotnet/wpf · error · InvalidOperationException

SR.FlowDocumentInvalidContnetChange

Error message

SR.FlowDocumentInvalidContnetChange

What it means

FlowDocument.OnPropertyChanged detects a property change (affecting measure/arrange/render) arriving while formatting is in progress, i.e. during layout. Re-entrantly modifying the document during its own formatting pass would corrupt the StructuralCache/NameTable, so the library flags the operation via OnInvalidOperationDetected and throws InvalidOperationException(SR.FlowDocumentInvalidContnetChange).

Solutions

  1. Defer property changes until after layout: use Dispatcher.BeginInvoke(DispatcherPriority.Background, ...) to apply the change
  2. Set properties before the document is displayed or outside measure/arrange callbacks
  3. Avoid binding FlowDocument layout-affecting properties to sources that update during rendering; use OneTime bindings or pre-set values
  4. Catch InvalidOperationException to log the re-entrancy and retry the change after layout completes

Example fix

// before
// inside OnRender/measure handler:
document.PagePadding = new Thickness(10); // throws if formatting in progress
// after
Dispatcher.BeginInvoke(DispatcherPriority.Background,
    new Action(() => document.PagePadding = new Thickness(10)));
Defensive patterns

Strategy: try-catch

Try / catch

try { doc.PagePadding = value; }
catch (InvalidOperationException) {
    Dispatcher.BeginInvoke(DispatcherPriority.Background,
        new Action(() => doc.PagePadding = value));
}

Prevention

When it happens

Trigger: Changing a FlowDocument or descendant DependencyProperty (e.g. setting PagePadding, ColumnWidth, fonts) from inside a measure/arrange pass, layout event, or a property-changed callback triggered while _structuralCache.IsFormattingInProgress is true.

Common situations: Setting FlowDocument properties inside a Loaded event, size-changed handler, or a binding that updates during layout; modifying page/column properties from custom pagination code that runs during formatting.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/FlowDocument.cs:796

            if (e.IsAValueChange || e.IsASubPropertyChange)
            {
                // Skip caches invalidation if content has not been formatted yet - non of caches are valid,
                // so they will be aquired during first formatting (full format).
                if (_structuralCache != null && _structuralCache.IsFormattedOnce)
                {
                    FrameworkPropertyMetadata fmetadata = e.Metadata as FrameworkPropertyMetadata;
                    if (fmetadata != null)
                    {
                        bool affectsRender = (fmetadata.AffectsRender &&
                            (e.IsAValueChange || !fmetadata.SubPropertiesDoNotAffectRender));
                        if (fmetadata.AffectsMeasure || fmetadata.AffectsArrange || affectsRender || fmetadata.AffectsParentMeasure || fmetadata.AffectsParentArrange)
                        {
                            // Detect invalid content change operations.
                            if (_structuralCache.IsFormattingInProgress)
                            {
                                _structuralCache.OnInvalidOperationDetected();
                                throw new InvalidOperationException(SR.FlowDocumentInvalidContnetChange);
                            }

                            // None of FlowDocument properties can invalidate structural caches (the NameTable),
                            // but most likely it invalidates format caches. Invalidate all format caches
                            // accumulated in the NameTable.
                            _structuralCache.InvalidateFormatCache(!affectsRender);

                            // Notify formatter about content invalidation.
                            _formatter?.OnContentInvalidated(!affectsRender);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Creates AutomationPeer (<see cref="ContentElement.OnCreateAutomationPeer"/>)
        /// </summary>

View on GitHub (pinned to 81131a70a4)