{"record":{"id":"f91944c7ab451e9e","repo":"dotnet/wpf","slug":"sr-format-sr-templatecircularreferencefound-name-walknode","errorCode":null,"errorMessage":"SR.Format(SR.TemplateCircularReferenceFound, name, walkNode.GetType())","messagePattern":"SR\\.Format\\(SR\\.TemplateCircularReferenceFound, name, walkNode\\.GetType\\(\\)\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/StyleHelper.cs","lineNumber":2079,"sourceCode":"                {\n                    nextParent = fceWalkNode.TemplatedParent;\n                }\n\n                // If we're beyond \"this\" container, check for identical Style & type\n                //  because that indicates a cycle.  If so, stop the train.\n                if( walkNode != container && nextParent != null ) // Only interested in nodes that are \"Not me\" and not auto-generated (== no TemplatedParent)\n                {\n                    // Do the cheaper comparison first - the Style reference should be cached\n                    if ((frameworkTemplate != null && walkNodeIsFE && feWalkNode.TemplateInternal == frameworkTemplate) )\n                    {\n                        // Then the expensive one - pulling in reflection to check if they're also the same types.\n                        if( walkNode.GetType() == container.GetType() )\n                        {\n                            string name = (walkNodeIsFE) ? feWalkNode.Name : fceWalkNode.Name;\n\n                            // Same Style, Same type, on a chain of Style-created nodes.\n                            //  This is bad news since this chain will continue indefinitely.\n                            throw new InvalidOperationException(\n                                SR.Format(SR.TemplateCircularReferenceFound, name, walkNode.GetType()));\n                        }\n                    }\n                }\n\n                // If the container is, in turn, created from another Style,\n                //  keep walking up that chain.  Exception:  do not walk up from a\n                //  ContentPresenter;  this avoids false positives involving a\n                //  ContentControl whose effective ContentTemplate contains another\n                //  instance of the same type of ContentControl, for example:\n                //          <Button Content=\"A\">\n                //              <Button.ContentTemplate>\n                //                  <DataTemplate>\n                //                      <Button Content=\"B\"/>\n                //                  </DataTemplate>\n                //              </Button.ContentTemplate>\n                //          </Button>\n                //  Both Buttons have the same ControlTemplate, which would be flagged","sourceCodeStart":2061,"sourceCodeEnd":2097,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/StyleHelper.cs#L2061-L2097","documentation":"During template expansion, the walk up the chain of Style/Template-generated containers found an element of the same type with the same style as the container, meaning the template re-applies itself and would recurse infinitely. WPF throws InvalidOperationException (TemplateCircularReferenceFound) naming the element and type.","triggerScenarios":"A ControlTemplate whose root element uses a Style that targets the same control type and applies the same template back; DefaultStyleKey/Style re-assignment creating a self-referencing template chain.","commonSituations":"Restyling a templated control's root with a style keyed by the same type (implicit style) that includes the same ControlTemplate; accidentally omitting a TemplateBinding to break the loop; copying a template into a style applied to its own root.","solutions":["Change the inner style to target a different element type or remove the template from it","Use BasedOn and override the inner root's Template to a distinct, non-recursive template","Apply the inner style via explicit key (x:Key) rather than the implicit type style","Break the chain by not styling the template's root element with the same style as the templated parent"],"exampleFix":"<!-- before: implicit style reapplies same template to the template root -->\n<Style TargetType=\"ListBoxItem\"><Setter Property=\"Template\"><Setter.Value><ControlTemplate TargetType=\"ListBoxItem\"><Border Style=\"{StaticResource listBoxItemStyle}\"/></ControlTemplate></Setter.Value></Setter></Style>\n// after: use a keyed style for the root that does not set the same Template\n<Style x:Key=\"itemRoot\" TargetType=\"Border\"><Setter Property=\"Background\" Value=\"Transparent\"/></Style>","handlingStrategy":"validation","validationCode":"// Before applying, ensure the template's root does not carry the same implicit style\nvar rootStyle = (Style)root.FindResource(root.GetType());\nif (rootStyle != null && Equals(rootStyle, containerStyle))\n    throw new InvalidOperationException(\"Template self-reference detected\");","typeGuard":null,"tryCatchPattern":"try { control.Template = tpl; } catch (InvalidOperationException ex) when (ex.Message.Contains(\"Circular\")) { Log(\"Template cycle for \" + control.GetType().Name); control.Template = null; }","preventionTips":["Never style the template's root element with a style that sets the same template","Use x:Key styles for inner elements instead of implicit type styles","Draw the style/template chain on paper for custom control themes","Keep inner root templates distinct via BasedOn overrides"],"tags":["wpf","templates","recursion","infinite-loop"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}