dotnet/wpf · error · InvalidOperationException
SR.CyclicStyleReferenceDetected
Error message
SR.CyclicStyleReferenceDetected
What it means
While a style is being applied, FrameworkElement checks that the incoming style does not create a reference cycle (e.g. a style whose BasedOn chain or resource lookup loops back to the element itself). If a cycle is detected during the style update, it throws InvalidOperationException(SR.CyclicStyleReferenceDetected) with the element in the message.
Solutions
- Break the BasedOn/resource cycle: make the style chain acyclic and remove self-referencing resource keys
- Use {DynamicResource} indirection carefully so the target style is not itself re-entered during update
- Rename conflicting resource keys so the lookup does not resolve back to the same style/element
Example fix
<!-- before: self-referencing BasedOn -->
<Style x:Key="s" TargetType="Button" BasedOn="{StaticResource s}"/>
<!-- after: base style separate from derived -->
<Style x:Key="base" TargetType="Button"/>
<Style x:Key="s" TargetType="Button" BasedOn="{StaticResource base}"/> Defensive patterns
Strategy: validation
Validate before calling
// Walk the BasedOn chain and reject cycles before assigning
Style s = candidate; var seen = new HashSet<Style>();
while (s != null) { if (!seen.Add(s)) throw new InvalidOperationException("Cyclic style reference detected."); s = s.BasedOn; } Type guard
bool IsAcyclicStyle(Style style) { var seen = new HashSet<Style>(); for (var s = style; s != null; s = s.BasedOn) if (!seen.Add(s)) return false; return true; } Try / catch
try { el.Style = candidate; } catch (InvalidOperationException ex) when (ex.Message.Contains("cyclic")) { /* inspect and repair the BasedOn/resource chain */ } Prevention
- Keep BasedOn chains acyclic; never base a style on its own key
- Avoid templates that set their own Style property
- Check resource-dictionary merges for mutually referencing style keys
When it happens
Trigger: Setting FrameworkElement.Style to a Style that (transitively, via BasedOn or DynamicResource references) references the same element/style — detected because IsStyleUpdateInProgress is already true when the update re-enters.
Common situations: Style with BasedOn={StaticResource self-referencing key}; a control template setting its own Style; resource dictionaries with mutually referencing styles where the loop resolves back to the same element.
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
- exceptionMessage.ToString()
- SR.ApplicationShuttingDown
- SR.BamlIsNotSupportedOutsideOfApplicationResources
- SR.CannotBeSelfParent
- SR.CannotBeSelfParent
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/125c97723e2db590.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/generators/FrameworkElementTemplate.cs:707
{
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([[instance.ThisString]]);
// Update the ContextMenu and ToolTips separately because they aren't in the tree
ContextMenu contextMenu =View on GitHub (pinned to 81131a70a4)