dotnet/wpf · error · InvalidOperationException

SR.Format(SR.TypeValueSerializerUnavailable…

Error message

SR.Format(SR.TypeValueSerializerUnavailable, this.GetType().Name )

What it means

After obtaining a context, ConvertToString asks it for the ValueSerializer of System.Type (context.GetValueSerializerFor(typeof(Type))). If the context supplies none, the command's OwnerType cannot be serialized as an xmlns-qualified class name, so InvalidOperationException (SR.TypeValueSerializerUnavailable) is thrown.

Solutions

  1. Use the standard WPF/XAML serialization context (e.g., from the designer's SerializerContext or values produced by XamlReader/Writer pipelines) which registers TypeValueSerializer.
  2. Register/provide a Type ValueSerializer in your custom ITypeDescriptorContext (see TypeValueSerializer in PresentationFramework).
  3. Fall back to manual formatting: $"{ClrNamespace(command.OwnerType)}:{command.OwnerType.Name}.{command.Name}Command" when no context-provided serializer exists.

Example fix

// before
typeSerializer = context.GetValueSerializerFor(typeof(Type));
return $"{typeSerializer.ConvertToString(command.OwnerType, context)}.{command.Name}Command";

// after
var typeSerializer = context?.GetValueSerializerFor(typeof(Type));
if (typeSerializer == null)
    return $"{command.OwnerType.FullName}.{command.Name}Command"; // fallback
return $"{typeSerializer.ConvertToString(command.OwnerType, context)}.{command.Name}Command";
Defensive patterns

Strategy: fallback

Validate before calling

var typeSerializer = context?.GetValueSerializerFor(typeof(Type));
if (typeSerializer == null)
    return $"{command.OwnerType.FullName}.{command.Name}Command"; // fallback path

Type guard

bool HasTypeSerializer(ITypeDescriptorContext ctx) => ctx?.GetValueSerializerFor(typeof(Type)) != null;

Try / catch

try { s = serializer.ConvertToString(command, context); }
catch (InvalidOperationException ex) when (ex.Message.Contains("ValueSerializer"))
{ s = $"{command.OwnerType.FullName}.{command.Name}Command"; }

Prevention

When it happens

Trigger: ConvertToString called with a custom or minimal ITypeDescriptorContext implementation that returns null from GetValueSerializerFor(typeof(Type)).

Common situations: Rehosting WPF designer services with incomplete type-descriptor providers; using a hand-rolled context in tests or custom markup serializers that lacks the built-in Type value serializer.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/Command/CommandValueSerializer.cs:82

                    // Known Commands, so write shorter version
                    if (CommandConverter.IsKnownType(command.OwnerType))
                    {
                        return command.Name;
                    }
                    else
                    {
                        ValueSerializer typeSerializer = null;

                        if (context == null)
                        {
                            throw new InvalidOperationException(SR.Format(SR.ValueSerializerContextUnavailable, this.GetType().Name ));
                        }

                        // Get the ValueSerializer for the System.Type type
                        typeSerializer = context.GetValueSerializerFor(typeof(Type));
                        if (typeSerializer == null)
                        {
                            throw new InvalidOperationException(SR.Format(SR.TypeValueSerializerUnavailable, this.GetType().Name ));
                        }

                        return $"{typeSerializer.ConvertToString(command.OwnerType, context)}.{command.Name}Command";
                    }
                }
            }
            else
                return string.Empty;
            
            throw GetConvertToException(value, typeof(string));
        }

        public override IEnumerable<Type> TypeReferences(object value, IValueSerializerContext context)
        {
            if (value != null)
            {
                RoutedCommand command = value as RoutedCommand;
                if (command != null)

View on GitHub (pinned to 81131a70a4)