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
- Use the extension only as: <ResourceDictionary Source="{ThemeDictionary AssemblyName}"/> or wrapping a ResourceDictionary element.
- Move the extension from the incorrect property to the ResourceDictionary Source.
- 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
- Only use {ThemeDictionary} as <ResourceDictionary Source="{ThemeDictionary X}"/>.
- Never paste the extension onto non-dictionary properties.
- Review merged-dictionary XAML after copy/paste refactors.
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
- IAmbientProvider
- IXamlSchemaContextProvider
- NotSupportedException
- SR.ColorConvertedBitmapExtensionNoSourceImage
- SR.ColorConvertedBitmapExtensionNoSourceProfile
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 nameView on GitHub (pinned to 81131a70a4)