dotnet/wpf · error · InvalidEnumArgumentException
InvalidEnumArgumentException(nameof(value), (int)modifiers…
Error message
InvalidEnumArgumentException(nameof(value), (int)modifiers, typeof(ModifierKeys))
What it means
ModifierKeysConverter.ConvertTo converts a ModifierKeys value to its string representation (e.g. 'Control+Alt'). Before converting it verifies the value is one of the defined ModifierKeys enum values; if the boxed value is not a valid ModifierKeys, an InvalidEnumArgumentException is thrown. This guards the converter against foreign or out-of-range values passed to the type conversion pipeline.
Solutions
- Validate the value is a defined ModifierKeys member before calling ConvertTo (e.g. Enum.IsDefined(typeof(ModifierKeys), value)).
- Ensure the object passed in is actually a ModifierKeys instance, not a raw int or another enum.
- Check the destinationType parameter is typeof(string).
- Catch InvalidEnumArgumentException at the conversion boundary and substitute ModifierKeys.None or a fallback rendering.
Example fix
// before
var text = converter.ConvertTo(keyValue, typeof(string)); // keyValue may be (ModifierKeys)999
// after
if (Enum.IsDefined(typeof(ModifierKeys), keyValue))
text = converter.ConvertTo(keyValue, typeof(string));
else
text = converter.ConvertTo(ModifierKeys.None, typeof(string)); Defensive patterns
Strategy: validation
Validate before calling
bool canConvert = value is ModifierKeys mk && Enum.IsDefined(typeof(ModifierKeys), mk) && destinationType == typeof(string);
Type guard
static bool IsValidModifierKeys(object v) => v is ModifierKeys mk && Enum.IsDefined(typeof(ModifierKeys), mk);
Try / catch
try { return converter.ConvertTo(value, typeof(string)); }
catch (InvalidEnumArgumentException) { return string.Empty; } Prevention
- Only pass ModifierKeys instances into the converter.
- Check Enum.IsDefined before any enum-to-string conversion.
- Validate destinationType is typeof(string) beforehand.
When it happens
Trigger: Calling ConvertTo with a value that is not a ModifierKeys enum value, a value cast from an arbitrary int that falls outside the defined ModifierKeys set (e.g. (ModifierKeys)999), or a destinationType other than string (that path throws GetConvertToException first).
Common situations: Data binding or XAML serialization pipelines feeding user-supplied integers into the converter; deserializing old/persisted settings where the stored int no longer maps to a ModifierKeys member after enum changes.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Animation_UnrecognizedHandoffBehavior
- args
- ArgumentOutOfRangeException(authentication)
- ArgumentOutOfRangeException(authenticationType)
- ArgumentOutOfRangeException(userActivationMode)
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9b7c01361c000c70.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs:109
/// Converts a <paramref name="value"/> of <see cref="ModifierKeys"/> to its <see langword="string"/> represensation.
/// </summary>
/// <param name="context">Serialization Context</param>
/// <param name="culture">Culture Info</param>
/// <param name="value">ModifierKeys value</param>
/// <param name="destinationType">Type to Convert</param>
/// <returns>A <see langword="string"/> representing the <see cref="ModifierKeys"/> specified by <paramref name="value"/>.</returns>
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
ArgumentNullException.ThrowIfNull(destinationType);
// We can only convert to string
if (destinationType != typeof(string))
throw GetConvertToException(value, destinationType);
// Check whether value falls within defined set
ModifierKeys modifiers = (ModifierKeys)value;
if (!IsDefinedModifierKeys(modifiers))
throw new InvalidEnumArgumentException(nameof(value), (int)modifiers, typeof(ModifierKeys));
// This is a fast path for when only a single modifier (or none) is set, which is a very common scenario.
// Therefore we want a fast path with an allocation free return, taking advantage of interned strings.
return modifiers switch
{
ModifierKeys.None => string.Empty,
ModifierKeys.Control => "Ctrl",
ModifierKeys.Alt => "Alt",
ModifierKeys.Shift => "Shift",
ModifierKeys.Windows => "Windows",
// Since we were not able to match a single modifier alone, there must be multiple modifiers involved.
_ => ConvertMultipleModifiers(modifiers),
};
}
private static string ConvertMultipleModifiers(ModifierKeys modifiers)
{
// Ctrl+Alt+Windows+Shift is the maximum char length, though the composition of such value is improbableView on GitHub (pinned to 81131a70a4)