libnyanpasu/clash-nyanpasu · error

invalid hotkey function: {s}

Error message

invalid hotkey function: {s}

What it means

HotkeyFunc::from_str parses user-provided hotkey function name strings (from config) into the HotkeyFunc enum. Unknown strings bail with 'invalid hotkey function: {s}'. The config file contained a function name that is not one of the recognized verbs (toggle/enable/disable system proxy or tun mode, etc.).

Source

Thrown at backend/tauri/src/core/hotkey.rs:142

}

impl FromStr for HotkeyFunc {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        match s {
            "open_or_close_dashboard" => Ok(HotkeyFunc::OpenOrCloseDashboard),
            "clash_mode_rule" => Ok(HotkeyFunc::ClashModeRule),
            "clash_mode_global" => Ok(HotkeyFunc::ClashModeGlobal),
            "clash_mode_direct" => Ok(HotkeyFunc::ClashModeDirect),
            "clash_mode_script" => Ok(HotkeyFunc::ClashModeScript),
            "toggle_system_proxy" => Ok(HotkeyFunc::ToggleSystemProxy),
            "enable_system_proxy" => Ok(HotkeyFunc::EnableSystemProxy),
            "disable_system_proxy" => Ok(HotkeyFunc::DisableSystemProxy),
            "toggle_tun_mode" => Ok(HotkeyFunc::ToggleTunMode),
            "enable_tun_mode" => Ok(HotkeyFunc::EnableTunMode),
            "disable_tun_mode" => Ok(HotkeyFunc::DisableTunMode),
            _ => bail!("invalid hotkey function: {s}"),
        }
    }
}

pub struct Hotkey {
    current: Arc<Mutex<Vec<String>>>, // 保存当前的热键设置

    app_handle: Arc<Mutex<Option<AppHandle>>>,
}
// (hotkey, func)
type HotKeyOp<'a> = (&'a str, HotKeyOpType<'a>);

#[derive(Debug)]
enum HotKeyOpType<'a> {
    #[allow(unused)]
    Unbind(&'a str),
    #[allow(unused)]
    Change(&'a str, &'a str),

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Fix the config entry to use an exact supported name (e.g. toggle_system_proxy, enable_tun_mode)
  2. Validate hotkey config at load/patch time and reject unknown functions with a clear UI message before application
  3. Keep a deprecated-name alias map to migrate old function names on config load

Example fix

// config before
"hotkey": { "Ctrl+Alt+P": "toggle_sys_proxy" }
// after
"hotkey": { "Ctrl+Alt+P": "toggle_system_proxy" }
Defensive patterns

Strategy: validation

Validate before calling

const VALID_FUNCS: [&str; 9] = ["open_or_close_dashboard","clash_mode_rule","clash_mode_global","clash_mode_direct","toggle_system_proxy","enable_system_proxy","disable_system_proxy","toggle_tun_mode","enable_tun_mode","disable_tun_mode"];
fn hotkey_func_valid(s: &str) -> bool { VALID_FUNCS.contains(&s) }

Try / catch

match s.parse::<HotkeyFunc>() {
    Ok(f) => f,
    Err(e) => return Err(config_error(format!("unknown hotkey function: {e}"))),
}

Prevention

When it happens

Trigger: A verge config hotkey mapping whose value is not one of the exact known strings — typos like 'toggle_sys_proxy', older/renamed function names, or non-English entries.

Common situations: Hand-edited config files; config migrated from an older version whose function names changed; users copying hotkey configs between forks with different verbs.

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


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/9d186134bd21f3f1. Report an issue: GitHub.