dotnet/wpf · error · InvalidOperationException

SR.ResourceDictionaryInvalidMergedDictionary

Error message

SR.ResourceDictionaryInvalidMergedDictionary

What it means

Thrown as InvalidOperationException from OnHierarchyInvalidated/owner registration (AddOwner path for FrameworkElement) when a merged ResourceDictionary would create a cycle — the element already owns this dictionary and the dictionary graph contains a cycle back to itself. WPF forbids circular merged-dictionary chains.

Solutions

  1. Break the cycle: remove the MergedDictionaries entry that points back to an ancestor dictionary
  2. Extract shared resources into a third dictionary that both merge, instead of cross-merging
  3. Draw the merged-dictionary graph and ensure it is a DAG
  4. Replace runtime self-merge code with a single well-known source dictionary

Example fix

// before
// DictA.MergedDictionaries contains DictB and DictB.MergedDictionaries contains DictA
// after
var shared = new ResourceDictionary { Source = new Uri("shared.xaml", UriKind.Relative) };
dictA.MergedDictionaries.Add(shared);
dictB.MergedDictionaries.Add(shared); // no cycle
Defensive patterns

Strategy: validation

Validate before calling

bool wouldCycle = dict.MergedDictionaries.Contains(target) || ContainsCycleTransitively(dict, target);

Try / catch

try { dict.AddOwner(fe); } catch (InvalidOperationException) { /* remove offending MergedDictionaries entry */ }

Prevention

When it happens

Trigger: Calling AddOwner (or MergedDictionaries.Add producing an ownership link) where the same FrameworkElement is already an owner of the dictionary and ContainsCycle(this) detects a loop, e.g. dictionary A merges B and B merges A.

Common situations: Two resource dictionaries merged into each other; a UserControl's resources merging a dictionary that (transitively) merges the control's own resources; theme/generic.xaml chains that loop after refactoring.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs:1506

                    // do not call AddInheritanceContextToValues -
                    // the owner is an Application, and we'll be
                    // calling SealValues soon, which takes care
                    // of InheritanceContext as well
                }

            }

            FrameworkElement fe = owner as FrameworkElement;
            if (fe != null)
            {
                if (_ownerFEs == null)
                {
                    _ownerFEs = new WeakReferenceList(1);
                }
                else if (_ownerFEs.Contains(fe) && ContainsCycle(this))
                {
                    throw new InvalidOperationException(SR.ResourceDictionaryInvalidMergedDictionary);
                }

                // Propagate the HasImplicitStyles flag to the new owner
                if (HasImplicitStyles)
                {
                    fe.ShouldLookupImplicitStyles = true;
                }

                _ownerFEs.Add(fe);
            }
            else
            {
                FrameworkContentElement fce = owner as FrameworkContentElement;
                if (fce != null)
                {
                    if (_ownerFCEs == null)
                    {
                        _ownerFCEs = new WeakReferenceList(1);

View on GitHub (pinned to 81131a70a4)