dotnet/wpf · error · InvalidOperationException

SR.ExpectedResourceDictionaryTarget

Error message

SR.ExpectedResourceDictionaryTarget

What it means

Inside ConvertFrom, after obtaining IProvideValueTarget, the converter checks that the target object receiving the deferred content is a ResourceDictionary. Deferred content is only meaningful inside a ResourceDictionary; if the value target is any other object the converter throws InvalidOperationException.

Solutions

  1. Only use DeferrableContentConverter for values that live inside a ResourceDictionary (e.g. deferred BAML entries of a .xaml resource dictionary)
  2. Remove a custom DeferringLoader/ValueSerializer assignment from types that are not ResourceDictionary content
  3. If building a test harness, register an IProvideValueTarget whose TargetObject is a real ResourceDictionary instance

Example fix

// before
typeDescriptorContext.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget
// returns a target that is not a ResourceDictionary
// after
var ipvt = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget));
if (ipvt.TargetObject is ResourceDictionary) { /* safe to proceed */ }
Defensive patterns

Strategy: type-guard

Validate before calling

var ipvt = provider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (ipvt?.TargetObject is not ResourceDictionary)
    throw new InvalidOperationException("DeferrableContentConverter may only target a ResourceDictionary.");

Type guard

static bool TargetsResourceDictionary(IServiceProvider p) =>
    (p.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget)?.TargetObject is ResourceDictionary;

Try / catch

try { return (DeferrableContent)converter.ConvertFrom(ctx, culture, value); }
catch (InvalidOperationException ex) when (ex.Message.Contains("ResourceDictionary")) { /* handle non-dictionary target */ }

Prevention

When it happens

Trigger: Invoking DeferrableContentConverter.ConvertFrom when the IProvideValueTarget.TargetObject returned by the service provider is not a ResourceDictionary — i.e. the deferral loader is being applied outside a dictionary, such as directly in a control's property or in a non-dictionary resource scope.

Common situations: Manually constructing a service provider for a ValueSerializer/TypeConverter test, copying a DeferringLoader attribute onto a type not used inside ResourceDictionary, or WPF internals changed by a framework version mismatch so the target is typed differently.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/DeferrableContentConverter.cs:49

                XamlSchemaContext xamlSchemaContext =
                    RequireService<IXamlSchemaContextProvider>(context).SchemaContext;
                Baml2006SchemaContext schemaContext = xamlSchemaContext as Baml2006SchemaContext;
                if (schemaContext == null)
                {
                    throw new InvalidOperationException(SR.ExpectedBamlSchemaContext);
                }

                IXamlObjectWriterFactory objectWriterFactory =
                    RequireService<IXamlObjectWriterFactory>(context);
                IProvideValueTarget ipvt =
                    RequireService<IProvideValueTarget>(context);
                IRootObjectProvider rootObjectProvider =
                    RequireService<IRootObjectProvider>(context);

                ResourceDictionary dictionary = ipvt.TargetObject as ResourceDictionary;
                if (dictionary == null)
                {
                    throw new InvalidOperationException(SR.ExpectedResourceDictionaryTarget);
                }

                Stream stream = value as Stream;
                if (stream == null)
                {
                    byte[] bytes = value as byte[];
                    if (bytes != null)
                    {
                        stream = new MemoryStream(bytes);
                    }
                }
                if (stream == null)
                {
                    throw new InvalidOperationException(SR.ExpectedBinaryContent);
                }

                // we shouldn't pass around the service provider
                DeferrableContent deferrableContext = new DeferrableContent(stream, schemaContext,

View on GitHub (pinned to 81131a70a4)