dotnet/wpf · error · InvalidOperationException

SR.Format(SR.CyclicStyleReferenceDetected, this)

Error message

SR.Format(SR.CyclicStyleReferenceDetected, this)

What it means

FrameworkElement.UpdateStyleProperty detects re-entrancy: the StyleProperty update is invoked (via OnInitialized, InvalidateTreeDependentProperties, InvalidateOnTreeChange, OnResourcesChanged, or InvalidateStyleAndReferences) while IsStyleUpdateInProgress is already true, meaning the style resolution looped back onto the same element. WPF throws InvalidOperationException (CyclicStyleReferenceDetected) to stop infinite recursion.

Solutions

  1. Remove any Setter/trigger that sets StyleProperty within a style, and check BasedOn chains for self-referencing DynamicResource keys.
  2. Defer style changes made in OnInitialized/OnResourcesChanged overrides with Dispatcher.BeginInvoke.
  3. Keep DefaultStyleKeyProperty.OverrideMetadata values static per type; never change them in response to style invalidation.
  4. Use the exception message (it includes the element) to identify the offending element and inspect its Style and resource keys.

Example fix

// before
var s = new Style(typeof(Button), (Style)Application.Current.Resources["self"]); // resources["self"] BasedOn this style -> cycle

// after
var s = new Style(typeof(Button), (Style)Application.Current.Resources["baseButtonStyle"]); // distinct base style
Defensive patterns

Strategy: validation

Validate before calling

if (element.IsStyleUpdateInProgress)
    throw new InvalidOperationException("Style update already in progress; defer the style change.");

Type guard

bool IsSafeForStyleUpdate(FrameworkElement e) => !e.IsStyleUpdateInProgress;

Try / catch

try
{
    element.Style = newStyle;
}
catch (InvalidOperationException ex) when (ex.Message.Contains("cyclic"))
{
    Log.Warn("Cyclic style reference detected.", ex);
}

Prevention

When it happens

Trigger: A style (or its BasedOn chain, setters, or triggers) triggers a style invalidation of the same element before the in-progress update completes — e.g. a Setter that sets Style, DynamicResource references that change Style during lookup, or overrides of OnInitialized/OnResourcesChanged that re-apply styles.

Common situations: A style Setter targeting StyleProperty itself; mutually referencing styles via BasedOn with DynamicResource; changing DefaultStyleKey/Style inside style callbacks; implicit styles that reference resources whose change invalidates the style again.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Generated/FrameworkElement.cs:625

        {
            if (!HasStyleInvalidated)
            {
                if (IsStyleUpdateInProgress == false)
                {
                    IsStyleUpdateInProgress = true;
                    try
                    {
                        InvalidateProperty(StyleProperty);
                        HasStyleInvalidated = true;
                    }
                    finally
                    {
                        IsStyleUpdateInProgress = false;
                    }
                }
                else
                {
                    throw new InvalidOperationException(SR.Format(SR.CyclicStyleReferenceDetected, this));
                }
            }
        }

        /// <summary>
        ///     This method causes the ThemeStyleProperty to be re-evaluated
        /// </summary>
        internal void UpdateThemeStyleProperty()
        {
            if (IsThemeStyleUpdateInProgress == false)
            {
                IsThemeStyleUpdateInProgress = true;
                try
                {
                    StyleHelper.GetThemeStyle(/* fe = */ this, /* fce = */ null);

                    // Update the ContextMenu and ToolTips separately because they aren't in the tree
                    ContextMenu contextMenu =

View on GitHub (pinned to 81131a70a4)