dotnet/wpf · error · ArgumentException
SR.Format(SR.CannotConvertStringToType…
Error message
SR.Format(SR.CannotConvertStringToType, keyToken.ToString(), typeof(Key))
What it means
KeyConverter.GetKeyFromString converts a string like 'A' or '5' to a Key. Single characters are mapped to Key.A/Key.D0 ranges only for ASCII letters and digits; any other single-character token (e.g. ',' or '€') that is not handled falls through and throws ArgumentException with CannotConvertStringToType including the token and typeof(Key).
Solutions
- Use valid Key names (enum names like 'Enter', 'D1', 'OemComma') or ASCII letters/digits
- Verify the shortcut string with a lookup before conversion (KeyConverter.IsValid or Enum.TryParse<Key>)
- Fix the config/XAML value to use the documented key token format
- Pre-parse with the supported separator '+' and validate each token
Example fix
// before
var key = (Key)new KeyConverter().ConvertFromString(","); // throws
// after
string token = ",";
Key key;
if (!Enum.TryParse(token, ignoreCase: true, out key))
key = Key.OemComma; // or reject input Defensive patterns
Strategy: validation
Validate before calling
bool ok = token.Length == 1 ? char.IsAsciiLetterOrDigit(token[0]) : Enum.TryParse<Key>(token, ignoreCase: true, out _);
if (!ok) throw new FormatException($"'{token}' is not a valid Key"); Type guard
static bool IsValidKeyToken(string s) => s.Length == 1 ? char.IsAsciiLetterOrDigit(s[0]) : Enum.TryParse<Key>(s, ignoreCase: true, out _);
Try / catch
try { var key = (Key)new KeyConverter().ConvertFromString(token); }
catch (ArgumentException ex) { log.Error($"Cannot convert '{token}' to Key: {ex.Message}"); } Prevention
- Validate shortcut strings before calling the converter
- Use enum Key names for non-alphanumeric keys (e.g. OemComma, Enter)
- Restrict user/config input to ASCII letters, digits, and known Key names
When it happens
Trigger: Calling KeyConverter.ConvertFrom (or ConvertFromInvariantString) with a one-character string that is not an ASCII digit or A–Z letter and is not a named key (e.g. ',', ';', or a non-ASCII character) — within the switch paths where keyToken.Length==1.
Common situations: Parsing keyboard shortcuts from config/XAML with wrong separators (e.g. 'Ctrl+,' semantics assumed), localized key names, or typos like 'Ctrl+Å' that don't map to a Key enum member.
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.Unsupported_Modifier, modifier.ToString())
- 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/0f9eff8016a70be9.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/KeyConverter.cs:123
// If the token is empty, we presume "None" as our value but it is a success
if (keyToken.IsEmpty)
return Key.None;
// In case we're dealing with a lowercase character, we uppercase it
char firstChar = keyToken[0];
if (firstChar >= 'a' && firstChar <= 'z')
firstChar ^= (char)0x20;
// If this is a single-character we're dealing with, match digits/letters
if (keyToken.Length == 1 && char.IsLetterOrDigit(firstChar))
{
// Match an ASCII digit or an ASCII letter (lower/uppercase)
if (char.IsAsciiDigit(firstChar)) // 0 - 9
return Key.D0 + firstChar - '0';
else if (char.IsAsciiLetterUpper(firstChar)) // A - Z
return Key.A + firstChar - 'A';
else
throw new ArgumentException(SR.Format(SR.CannotConvertStringToType, keyToken.ToString(), typeof(Key)));
}
// It is a special key or an invalid one, we're gonna find out
switch (keyToken.Length)
{
case 2:
// Special path for F1-F9 (switch would take 600 B in code size for no benefit)
char secondChar = keyToken[1];
if (firstChar == 'F' && (secondChar > '0' && secondChar <= '9'))
return Key.F1 + secondChar - '1';
// We've got one more special case for Key.Back/Backspace -> "BS"
if (firstChar == 'B' && (secondChar is 'S' or 's'))
return Key.Back;
break;
case 3:
switch (firstChar)
{
case 'A':View on GitHub (pinned to 81131a70a4)