dotnet/wpf · error · InvalidOperationException

SR.Format(SR.ValueSerializerContextUnavailable…

Error message

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

What it means

CommandValueSerializer.ConvertToString serializes an RoutedCommand as "ns:Class.NameCommand", which requires an ITypeDescriptorContext to look up the ValueSerializer for System.Type. When context is null it cannot resolve the owner type and throws InvalidOperationException (SR.ValueSerializerContextUnavailable).

Solutions

  1. Provide a valid ITypeDescriptorContext (e.g., obtained from TypeDescriptor context or the WPF XAML designer host) instead of null.
  2. Outside XAML serialization, format the command directly: $"{command.OwnerType.FullName}.{command.Name}Command".
  3. Guard the call site: skip serializer-based conversion when no context is available.

Example fix

// before
string s = serializer.ConvertToString(command, null);

// after
string s = command != null
    ? $"{command.OwnerType.AssemblyQualifiedName}" // or manual ns:Class formatting outside XAML
    : string.Empty;
Defensive patterns

Strategy: type-guard

Validate before calling

if (context == null)
    return $"{command.OwnerType.FullName}.{command.Name}Command"; // manual fallback
return serializer.ConvertToString(command, context);

Type guard

bool CanUseValueSerializer(ITypeDescriptorContext ctx) => ctx != null;

Try / catch

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

Prevention

When it happens

Trigger: Calling valueSerializer.ConvertToString(routedCommand, null) directly; invoking the serializer outside a XAML/type-descriptor pipeline that normally supplies the context.

Common situations: Custom serialization or designer tooling calling ValueSerializer APIs manually without building an ITypeDescriptorContext; unit tests passing null for context; logging code that tries to stringify commands via the serializer.

Related errors


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

Appendix: source

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

        public override string ConvertToString(object value, IValueSerializerContext context)
        {
            if (value != null)
            {
                RoutedCommand command = value as RoutedCommand;
                if (null != command && null != command.OwnerType)
                {
                    // 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));
        }

View on GitHub (pinned to 81131a70a4)