{"record":{"id":"9c9ab322fc0c8fdb","repo":"dotnet/wpf","slug":"sr-accesskeymanager-notaunicodecharacter","errorCode":null,"errorMessage":"SR.AccessKeyManager_NotAUnicodeCharacter","messagePattern":"SR\\.AccessKeyManager_NotAUnicodeCharacter","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/AccessKeyManager.cs","lineNumber":125,"sourceCode":"            AccessKeyManager akm = AccessKeyManager.Current;\n            return (akm.ProcessKeyForScope(scope, key, isMultiple,false) == ProcessKeyResult.MoreMatches);\n        }\n\n        /// <summary>\n        /// Returns StringInfo.GetNextTextElement(key).ToUpperInvariant() throwing exceptions for null\n        /// and multi-char strings.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        private static string NormalizeKey(string key)\n        {\n            ArgumentNullException.ThrowIfNull(key);\n\n            string firstCharacter = StringInfo.GetNextTextElement(key);\n\n            if (key != firstCharacter)\n            {\n                throw new ArgumentException(SR.Format(SR.AccessKeyManager_NotAUnicodeCharacter, \"key\"));\n            }\n\n            return firstCharacter.ToUpperInvariant();\n        }\n\n        /// <summary>\n        /// This event is used by elements that want to define a scope for accesskeys, such as Menu and Popup.\n        /// This event will never be raised, it is used to identify classes that define new scopes.\n        /// </summary>\n        public static readonly RoutedEvent AccessKeyPressedEvent = EventManager.RegisterRoutedEvent(\n            \"AccessKeyPressed\", RoutingStrategy.Bubble, typeof(AccessKeyPressedEventHandler), typeof(AccessKeyManager));\n\n        /// <summary>\n        ///     Adds a handler for the AccessKeyPressed attached event\n        /// </summary>\n        /// <param name=\"element\">UIElement or ContentElement that listens to this event</param>\n        /// <param name=\"handler\">Event Handler to be added</param>\n        public static void AddAccessKeyPressedHandler(DependencyObject element, AccessKeyPressedEventHandler handler)","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/AccessKeyManager.cs#L107-L143","documentation":"AccessKeyManager.NormalizeKey throws ArgumentException when the given access key string is not a single Unicode character (a text element). WPF access keys are exactly one character, so multi-character strings are rejected before normalization via ToUpperInvariant. The SR resource AccessKeyManager_NotAUnicodeCharacter supplies the message naming the offending 'key' argument.","triggerScenarios":"Calling AccessKeyManager.Register, Unregister, IsKeyRegistered, or ProcessKey with a key string whose full text differs from its first text element — i.e. any string longer than one grapheme, such as \"AB\", surrogate-pair misuse, or an empty string (empty yields firstCharacter=\"\" and \"\"!=\"\" is false only when key==\"\"... actually GetNextTextElement(\"\") returns \"\" so empty passes null check but throws here only when key.Length>1).","commonSituations":"Binding an access key to a label substring or a localized string without slicing out a single character; passing a user-typed string or a config value like \"F1\" or \"Esc\" instead of a single character; concatenating modifiers with the key (\"Ctrl+K\").","solutions":["Pass exactly one character: key.Substring(0,1) or a char.ToString() value.","Validate the string with StringInfo.GetNextTextElement(key) == key before calling the API.","Strip modifier prefixes (e.g. \"_\") and take only the access character, which is what UIHelper/Label does for _Mnemonics."],"exampleFix":"// before\nAccessKeyManager.Register(\"Ctrl+K\", window);\n// after\nAccessKeyManager.Register(\"K\", window);","handlingStrategy":"validation","validationCode":"static bool IsSingleUnicodeChar(string key) =>\n    !string.IsNullOrEmpty(key) && StringInfo.GetNextTextElement(key) == key;","typeGuard":"static string ToAccessKey(object value)\n{\n    var s = value as string;\n    return (s != null && s.Length == 1) ? s.ToUpperInvariant() : null;\n}","tryCatchPattern":"try { AccessKeyManager.Register(key, target); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"AccessKeyManager\"))\n{ /* log: key must be a single Unicode character */ }","preventionTips":["Always derive the access key from a single char (e.g. label text preceded by '_').","Never pass multi-character strings like \"Ctrl+K\" or \"F1\" to AccessKeyManager APIs.","Unit-test access key extraction with surrogate-pair characters."],"tags":["wpf","access-key","argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}