{"record":{"id":"e2a156210026ce74","repo":"shadowsocks/shadowsocks-windows","slug":"callbackname-not-found","errorCode":null,"errorMessage":"{callbackName} not found","messagePattern":"(.+?) not found","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"shadowsocks-csharp/Controller/HotkeyReg.cs","lineNumber":48,"sourceCode":"            }\n            else\n            {\n                RegHotkeyFromString(\"\", \"SwitchSystemProxyCallback\");\n                RegHotkeyFromString(\"\", \"SwitchSystemProxyModeCallback\");\n                RegHotkeyFromString(\"\", \"SwitchAllowLanCallback\");\n                RegHotkeyFromString(\"\", \"ShowLogsCallback\");\n                RegHotkeyFromString(\"\", \"ServerMoveUpCallback\");\n                RegHotkeyFromString(\"\", \"ServerMoveDownCallback\");\n                MessageBox.Show(I18N.GetString(\"Register hotkey failed\"), I18N.GetString(\"Shadowsocks\"));\n            }\n        }\n\n        public static bool RegHotkeyFromString(string hotkeyStr, string callbackName, Action<RegResult> onComplete = null)\n        {\n            var _callback = HotkeyCallbacks.GetCallback(callbackName);\n            if (_callback == null)\n            {\n                throw new Exception($\"{callbackName} not found\");\n            }\n\n            var callback = _callback as HotKeys.HotKeyCallBackHandler;\n\n            if (string.IsNullOrEmpty(hotkeyStr))\n            {\n                HotKeys.UnregExistingHotkey(callback);\n                onComplete?.Invoke(RegResult.UnregSuccess);\n                return true;\n            }\n            else\n            {\n                var hotkey = HotKeys.Str2HotKey(hotkeyStr);\n                if (hotkey == null)\n                {\n                    logger.Error($\"Cannot parse hotkey: {hotkeyStr}\");\n                    onComplete?.Invoke(RegResult.ParseError);\n                    return false;","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/shadowsocks/shadowsocks-windows/blob/891d971682eefcaa2e640258d3b352a3ad3b2233/shadowsocks-csharp/Controller/HotkeyReg.cs#L30-L66","documentation":"Thrown by RegHotkeyFromString when HotkeyCallbacks.GetCallback(callbackName) returns null, meaning no handler has been registered in the HotkeyCallbacks registry under the supplied name. The method is meant to resolve a string callback name (e.g. \"ShowLogsCallback\") to a HotKeyCallBackHandler delegate. This fires before any hotkey is actually registered with the OS, so it is purely an internal lookup failure, not an OS-level registration error.","triggerScenarios":"Calling RegHotkeyFromString with a callbackName string that was never registered via HotkeyCallbacks.Add(...). This also happens if the registration key string is misspelled, has different casing, or if the registration code path that adds the callback never ran (e.g. the view/controller that owns the callback was never instantiated).","commonSituations":"Refactoring a callback and renaming it in one place but not the string literal passed to RegHotkeyFromString; removing a feature (logs/move-up/move-down) but leaving the RegHotkeyFromString(\"\", \"ShowLogsCallback\") call behind; copy-pasting a new hotkey config line and forgetting to register the matching callback.","solutions":["Check HotkeyCallbacks for the exact registered name and make the string passed to RegHotkeyFromString match it exactly (case-sensitive).","If you removed the callback intentionally, also remove the RegHotkeyFromString call that references it.","If you added a new hotkey, register its handler with HotkeyCallbacks.Add(\"YourCallbackName\", handler) before RegHotkeyFromString runs."],"exampleFix":"// before\nRegHotkeyFromString(cfg.MoveUpKey, \"MoveUpCallback\"); // throws if not registered\n\n// after\nif (HotkeyCallbacks.GetCallback(\"MoveUpCallback\") != null)\n    RegHotkeyFromString(cfg.MoveUpKey, \"MoveUpCallback\");","handlingStrategy":"validation","validationCode":"// Before calling RegHotkeyFromString, confirm the callback exists\nif (HotkeyCallbacks.GetCallback(callbackName) == null)\n{\n    // skip or log instead of letting it throw\n    return false;\n}","typeGuard":"// Narrow to known callback names\nstatic readonly HashSet<string> KnownCallbacks =\n    new HashSet<string> { \"ShowLogsCallback\", \"ServerMoveUpCallback\", \"ServerMoveDownCallback\" };\n\nbool IsValidCallbackName(string name) => KnownCallbacks.Contains(name);","tryCatchPattern":"try { RegHotkeyFromString(hotkeyStr, callbackName); }\ncatch (Exception ex) when (ex.Message.EndsWith(\"not found\"))\n{ /* log unknown callback name, do not abort all hotkey registration */ }","preventionTips":["Keep callback name literals in one place (constants) so renames stay in sync with registration.","Register callbacks before any RegHotkeyFromString call runs.","Unit-test that every name passed to RegHotkeyFromString resolves via GetCallback."],"tags":["hotkey","registry","lookup","configuration"],"backgroundTag":null,"analyzedSha":"891d971682eefcaa2e640258d3b352a3ad3b2233","analyzedAt":"2026-08-13T10:12:34.434Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}