dotnet/wpf · error · ArgumentException
SR.Format(SR.MustBeOfType, "value", "SystemResourceKey or…
Error message
SR.Format(SR.MustBeOfType, "value", "SystemResourceKey or SystemThemeKey")
What it means
SystemKeyConverter.ConvertTo only accepts SystemResourceKey or SystemThemeKey as the value being converted; any other object type makes it throw ArgumentException. The converter exists so WPF system resource keys (e.g. SystemParameters.CaptionHeightKey) can round-trip to a StaticExtension markup string for XAML serialization. Passing an unconvertible value is a programming error, so the exception names the two accepted types.
Solutions
- Check the value's type before calling ConvertTo and only pass SystemResourceKey or SystemThemeKey instances.
- If converting other key kinds, dispatch to the correct converter (e.g. the TypeConverter for that key's type) instead of SystemKeyConverter.
- Wrap the ConvertTo call in try/catch(ArgumentException) when the input is untrusted and skip/convert via ToString() instead.
Example fix
// before
string s = (string)converter.ConvertTo(null, CultureInfo.InvariantCulture, value, typeof(MarkupExtension));
// after
if (value is SystemResourceKey || value is SystemThemeKey)
{
string s = (string)converter.ConvertTo(null, CultureInfo.InvariantCulture, value, typeof(MarkupExtension));
}
else
{
string s = value?.ToString() ?? string.Empty; // or skip non-system keys
} Defensive patterns
Strategy: type-guard
Validate before calling
if (value is SystemResourceKey || value is SystemThemeKey)
{
var ext = (MarkupExtension)converter.ConvertTo(null, CultureInfo.InvariantCulture, value, typeof(MarkupExtension));
}
else
{
throw new ArgumentException($"Cannot convert {value?.GetType().Name}; expected SystemResourceKey or SystemThemeKey");
} Type guard
bool IsSystemKey(object value) => value is SystemResourceKey || value is SystemThemeKey;
Try / catch
try
{
var ext = (MarkupExtension)converter.ConvertTo(null, culture, value, typeof(MarkupExtension));
}
catch (ArgumentException ex)
{
// value was not a system key; log and handle non-convertible input
} Prevention
- Only feed SystemResourceKey/SystemThemeKey instances into SystemKeyConverter
- Route other key types to their own TypeConverter
- Unit-test converters with representative value types
- Add a type assert/guard before ConvertTo in serialization helpers
When it happens
Trigger: Calling TypeConverter.ConvertTo (or TypeDescriptor.GetConverter(new SystemResourceKey(...)).ConvertTo(null, culture, value, destinationType)) with a value that is neither SystemResourceKey nor SystemThemeKey, e.g. passing a raw enum, a string, or a different key type.
Common situations: Custom XAML serialization/markup extension code that walks resource dictionaries and assumes every value is a system key; converters reused with arbitrary keys like DynamicResourceExtension values; refactoring that changed the key type without updating the converter call.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ArgumentNullException (nameof(targetObject))
- Can only countersign parts with Digital Signature…
- Cannot convert from type.
- Cannot convert from type.
- Cannot convert to type.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/5b9f24e4219eb7ab.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemKeyConverter.cs:132
if (destinationType == typeof(MarkupExtension)
&&
CanConvertTo(context, destinationType) )
{
SystemResourceKeyID keyId;
// Get the SystemResourceKeyID
if( value is SystemResourceKey )
{
keyId = (value as SystemResourceKey).InternalKey;
}
else if( value is SystemThemeKey )
{
keyId = (value as SystemThemeKey).InternalKey;
}
else
{
throw new ArgumentException(SR.Format(SR.MustBeOfType, "value", "SystemResourceKey or SystemThemeKey"));
}
// System resource keys can be converted into a MarkupExtension (StaticExtension)
Type keyType = SystemKeyConverter.GetSystemClassType(keyId);
// Get the value serialization context
IValueSerializerContext valueSerializerContext = context as IValueSerializerContext;
if( valueSerializerContext != null )
{
// And from that get a System.Type serializer
ValueSerializer typeSerializer = valueSerializerContext.GetValueSerializerFor(typeof(Type));
if( typeSerializer != null )
{
// And use that to create the string-ized class name
string systemClassName = typeSerializer.ConvertToString(keyType, valueSerializerContext);
// And finally create the StaticExtension.View on GitHub (pinned to 81131a70a4)