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
- Remove any Setter/trigger that sets StyleProperty within a style, and check BasedOn chains for self-referencing DynamicResource keys.
- Defer style changes made in OnInitialized/OnResourcesChanged overrides with Dispatcher.BeginInvoke.
- Keep DefaultStyleKeyProperty.OverrideMetadata values static per type; never change them in response to style invalidation.
- 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
- Never set StyleProperty from inside a style Setter, trigger, or style-invalidation callback.
- Check BasedOn chains and DynamicResource keys for self-references.
- Keep DefaultStyleKey metadata static per control type.
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
- SR.CannotBeSelfParent
- SR.Format(SR.CyclicThemeStyleReferenceDetected, this)
- SR.Format(SR.CyclicThemeStyleReferenceDetected, this)
- Animation_Invalid_DefaultValue
- Cannot remove signature from read-only file.
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)