{"record":{"id":"a27e4afe6eaca2b2","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-get-module-handle-err","errorCode":null,"errorMessage":"Failed to get module handle: {err}","messagePattern":"Failed to get module handle: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/shutdown_hook.rs","lineNumber":128,"sourceCode":"fn setup_shutdown_hook_inner(\n    f: impl Fn() + Send + Sync + 'static,\n    initd_tx: oneshot::Sender<()>,\n) -> anyhow::Result<()> {\n    let class_name = w!(\"TAURI_SHUTDOWN_HOOK\");\n\n    let (tx, rx) = std::sync::mpsc::channel::<()>();\n    std::thread::spawn(move || {\n        while let Ok(()) = rx.recv() {\n            f();\n        }\n    });\n\n    SHUTDOWN_HOOK_INSTANCE.set(tx).unwrap();\n\n    let h_instance = unsafe { GetModuleHandleW(std::ptr::null()) };\n    if h_instance.is_null() {\n        let err = Error::from_win32();\n        anyhow::bail!(\"Failed to get module handle: {err}\");\n    }\n\n    let mut window_class_ex = unsafe { std::mem::zeroed::<WNDCLASSEXW>() };\n    window_class_ex.cbSize = std::mem::size_of::<WNDCLASSEXW>() as u32;\n    window_class_ex.lpszClassName = class_name.as_ptr();\n    window_class_ex.lpfnWndProc = Some(callback);\n    window_class_ex.hInstance = h_instance;\n\n    unsafe {\n        if RegisterClassExW(&window_class_ex) == 0 {\n            let err = Error::from_win32();\n            anyhow::bail!(\"Failed to register window class: {err}\");\n        }\n    }\n\n    let window_name = w!(\"TAURI_SHUTDOWN_HOOK_WINDOW\");\n    let hidden_window = unsafe {\n        CreateWindowExW(","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/shutdown_hook.rs#L110-L146","documentation":"On Windows, the shutdown-hook thread needs the module handle of the running executable (GetModuleHandleW(null)) to register a window class for the hidden message-only window that receives WM_QUERYENDSESSION/console signals. If GetModuleHandleW returns null, the code converts the last OS error via Error::from_win32() and bails with this message, so hook setup fails before the window is created.","triggerScenarios":"Calling setup_shutdown_hook on Windows when GetModuleHandleW(std::ptr::null()) fails — e.g. the process image cannot be resolved (corrupted/unusual host process, limited execution context such as a service or embedded host where the module is not accessible), or Win32 returns an unexpected error at startup.","commonSituations":"Running the app inside an unusual Windows host (service host, non-standard launcher) where the executable module handle is unavailable; Windows API failures due to low resources or security software blocking module enumeration; running under constrained CI/service accounts.","solutions":["Inspect the Win32 error embedded in the message (err) and address its cause (permissions, host environment, resource limits)","Run the app as a normal user-launched process rather than inside a restrictive service host if signal handling via window messages is required","Add a fallback shutdown path (e.g. console ctrl handler via SetConsoleCtrlHandler) if GetModuleHandleW fails, instead of hard-failing setup","Log the error and continue app startup, treating graceful-signal shutdown as degraded (best-effort) rather than fatal"],"exampleFix":"// before: hard failure on missing module handle\nif h_instance.is_null() {\n    let err = Error::from_win32();\n    anyhow::bail!(\"Failed to get module handle: {err}\");\n}\n// after: degrade gracefully, keep app running without signal window\nif h_instance.is_null() {\n    let err = Error::from_win32();\n    log::warn!(\"shutdown signal window unavailable: {err}\");\n    return Ok(());\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = setup_shutdown_hook(on_shutdown) {\n    if e.to_string().starts_with(\"Failed to get module handle\") {\n        log::warn!(\"graceful shutdown signals unavailable: {e}; continuing\");\n    } else {\n        return Err(e);\n    }\n}","preventionTips":["Run the app as a normally launched user process, not inside a restrictive service host","Treat graceful signal handling as best-effort: degrade to normal exit if the Win32 setup fails","Include the Win32 error code in logs to diagnose host/permission issues quickly","Test hook setup on target Windows environments (service, CI, standard user) before release"],"tags":["windows","win32","shutdown","initialization"],"backgroundTag":"module-init-failed","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}