dotnet/wpf · error · InvalidOperationException

SR.ThemeDictionaryExtension_Source

Error message

SR.ThemeDictionaryExtension_Source

What it means

ThemeDictionaryExtension may only be applied to a ResourceDictionary, targeting either the dictionary itself or its Source property. If the target object is not a ResourceDictionary, or the target property is neither null nor the Source property, ProvideValue throws InvalidOperationException with SR.ThemeDictionaryExtension_Source.

Solutions

  1. Use the extension only as: <ResourceDictionary Source="{ThemeDictionary AssemblyName}"/> or wrapping a ResourceDictionary element.
  2. Move the extension from the incorrect property to the ResourceDictionary Source.
  3. If a plain theme URI is needed on another property, compute the pack URI in code instead.

Example fix

// before
<Setter Property="Background" Value="{ThemeDictionary MyApp}"/> <!-- throws -->
// after
<ResourceDictionary Source="{ThemeDictionary MyApp}"/>
Defensive patterns

Strategy: validation

Validate before calling

bool isOnDictionarySource = targetObject is ResourceDictionary &&
    (targetProperty == null || targetProperty == ThemeDictionaryExtension_SourceProperty);
if (!isOnDictionarySource) throw new InvalidOperationException("Place ThemeDictionary only on a ResourceDictionary's Source.");

Try / catch

try { return (Uri)ext.ProvideValue(sp); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Source") || ex.Message.Contains("ResourceDictionary")) { return null; }

Prevention

When it happens

Trigger: Placing {ThemeDictionary ...} on a property whose value is not a ResourceDictionary (e.g. a Brush, Uri, or Style property); applying it to a different property of a ResourceDictionary such as DeferredContent.

Common situations: Copy-paste of the markup extension into the wrong XAML attribute; misunderstanding that the extension must sit on <ResourceDictionary> or its Source attribute, not on arbitrary resource values.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ThemeDictionaryExtension.cs:86

                throw new InvalidOperationException(SR.ThemeDictionaryExtension_Name);
            }

            IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
            if( provideValueTarget == null )
            {
                throw new InvalidOperationException(SR.Format(SR.MarkupExtensionNoContext, GetType().Name, "IProvideValueTarget" ));
            }
                
            object targetObject = provideValueTarget.TargetObject;
            object targetProperty = provideValueTarget.TargetProperty;

            ResourceDictionary dictionary = targetObject as ResourceDictionary;
            PropertyInfo propertyInfo = targetProperty as PropertyInfo;

            // Allow targetProperty to be null or ResourceDictionary.Source
            if (dictionary == null || (targetProperty != null && propertyInfo != SourceProperty))
            {
                throw new InvalidOperationException(SR.ThemeDictionaryExtension_Source);
            }

            Register(dictionary, _assemblyName);
            dictionary.IsSourcedFromThemeDictionary = true;

            return GenerateUri(_assemblyName, SystemResources.ResourceDictionaries.ThemedResourceName, MS.Win32.UxThemeWrapper.ThemeName);
        }

        // Build the Uri for the assembly:
        // /AssemblyName;Component/themes/<CurrentTheme>.<Color>.xaml
        private static Uri GenerateUri(string assemblyName, string resourceName, ReadOnlySpan<char> themeName)
        {
            StringBuilder uri = new StringBuilder(assemblyName.Length + 50);

            uri.Append('/');
            uri.Append(assemblyName);

            // If assembly is PresentationFramework, append the Theme name

View on GitHub (pinned to 81131a70a4)