dotnet/wpf · error · NotSupportedException
SR.Format(SR.Unsupported_Modifier, modifier.ToString())
Error message
SR.Format(SR.Unsupported_Modifier, modifier.ToString())
What it means
ModifierKeysConverter.ConvertFrom parses modifier-key tokens into a ModifierKeys value. Recognized tokens are Ctrl/Control, Win/Windows, Alt, and Shift (case-insensitive); any other token reaches the switch discard arm and throws NotSupportedException with Unsupported_Modifier naming the offending token.
Solutions
- Use supported tokens only: Ctrl, Control, Win, Windows, Alt, Shift
- Normalize aliases before conversion (map 'Meta'/'Cmd' to 'Control' or 'Windows')
- Pre-validate each '+'-separated token against the supported list and report a friendly error
- Use ModifierKeysConverter.ConvertToString output as the canonical round-trip format
Example fix
// before
var mk = (ModifierKeys)new ModifierKeysConverter().ConvertFromString("Cmd"); // throws
// after
string token = "Cmd";
token = token.Equals("Cmd", StringComparison.OrdinalIgnoreCase) ? "Control" : token;
var mk = (ModifierKeys)new ModifierKeysConverter().ConvertFromString(token); Defensive patterns
Strategy: validation
Validate before calling
string[] supported = { "Ctrl","Control","Win","Windows","Alt","Shift" };
bool ok = supported.Contains(token, StringComparer.OrdinalIgnoreCase);
if (!ok) throw new FormatException($"Unsupported modifier: {token}"); Type guard
static bool IsSupportedModifier(string s) => s is "Ctrl" or "Control" or "Win" or "Windows" or "Alt" or "Shift" ||
new[]{"ctrl","control","win","windows","alt","shift"}.Contains(s.ToLowerInvariant()); Try / catch
try { var mk = (ModifierKeys)new ModifierKeysConverter().ConvertFromString(token); }
catch (NotSupportedException ex) { log.Error($"Unsupported modifier token: {ex.Message}"); } Prevention
- Normalize platform aliases (Cmd/Meta -> Control/Windows) before conversion
- Only accept the six documented tokens in hotkey settings
- Validate each '+'-separated gesture token before invoking the converter
When it happens
Trigger: Calling ConvertFrom/ConvertFromString with a gesture or settings string containing an unrecognized modifier such as 'Meta', 'Cmd', 'Super', or a misspelling like 'Shft', typically from '+'-separated gesture strings.
Common situations: Porting shortcuts from macOS/other frameworks ('Cmd+X'), user-edited hotkey configs, localization of key names, or migrating keybinding settings across platforms.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- SR.Format(SR.CannotConvertStringToType…
- ArgumentNullException (nameof(targetObject))
- 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/9623010af19391ab.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs:83
ModifierKeys modifiers = ModifierKeys.None;
foreach (Range token in modifiersToken.Split('+'))
{
ReadOnlySpan<char> modifier = modifiersToken[token].Trim();
// This would be a case where we have a token like "Ctrl + " for example,
// which itself is invalid but we choose to support this malformed behaviour.
if (modifier.IsEmpty)
break;
modifiers |= modifier switch
{
_ when modifier.Equals("Ctrl", StringComparison.OrdinalIgnoreCase) => ModifierKeys.Control,
_ when modifier.Equals("Control", StringComparison.OrdinalIgnoreCase) => ModifierKeys.Control,
_ when modifier.Equals("Win", StringComparison.OrdinalIgnoreCase) => ModifierKeys.Windows,
_ when modifier.Equals("Windows", StringComparison.OrdinalIgnoreCase) => ModifierKeys.Windows,
_ when modifier.Equals("Alt", StringComparison.OrdinalIgnoreCase) => ModifierKeys.Alt,
_ when modifier.Equals("Shift", StringComparison.OrdinalIgnoreCase) => ModifierKeys.Shift,
_ => throw new NotSupportedException(SR.Format(SR.Unsupported_Modifier, modifier.ToString()))
};
}
return modifiers;
}
/// <summary>
/// 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);
View on GitHub (pinned to 81131a70a4)