ramensoftware/windhawk · error · std::runtime_error
Failed to initialize MinHook
Error message
Failed to initialize MinHook
What it means
Windhawk's customization session initializes the MinHook hooking engine by calling MH_Initialize() during session construction. If MinHook reports any status other than MH_OK (e.g. it was already initialized or an internal buffer allocation failed), the scope constructor logs the status code and throws std::runtime_error to abort the session. A failed hooking-engine init means no hooks can be installed for the customization.
Solutions
- Check whether another customization session or module already called MH_Initialize and is still active; ensure sessions are torn down (MH_Uninitialize) before a new one starts.
- Read the logged MH_STATUS code: MH_ERROR_ALREADY_INITIALIZED means MinHook is usable as-is and the throw may be overly strict for your flow.
- Retry session creation once the conflicting session has exited.
- Report to Windhawk if it reproduces consistently with a single session, including the status code from the log.
Example fix
// before
MH_STATUS status = MH_Initialize();
if (status != MH_OK) {
LOG(L"MH_Initialize failed with %d", status);
throw std::runtime_error("Failed to initialize MinHook");
}
// after
MH_STATUS status = MH_Initialize();
if (status == MH_ERROR_ALREADY_INITIALIZED) {
LOG(L"MinHook already initialized; reusing");
} else if (status != MH_OK) {
LOG(L"MH_Initialize failed with %d", status);
throw std::runtime_error("Failed to initialize MinHook");
} Defensive patterns
Strategy: try-catch
Validate before calling
// best-effort pre-check: MinHook is already usable if MH_Initialize would return ALREADY_INITIALIZED // no public pre-check exists; catch and inspect the logged MH_STATUS instead
Try / catch
try {
auto session = CreateCustomizationSession(...);
} catch (const std::runtime_error& e) {
if (std::string_view(e.what()) == "Failed to initialize MinHook") {
LOG(L"MinHook init failed; retrying after cleanup");
// tear down conflicting sessions, then retry once
}
} Prevention
- Ensure each CustomizationSession owns MinHook exclusively; never nest sessions.
- Always pair MH_Initialize with MH_Uninitialize on the same thread/lifetime.
- Log MH_STATUS codes to distinguish already-initialized vs real failures.
- Wrap session creation so a failed init leaves no partially initialized state.
When it happens
Trigger: Creating a CustomizationSession with WH_HOOKING_ENGINE_MINHOOK enabled when MinHook is already initialized (MH_ERROR_ALREADY_INITIALIZED), or when MH_Initialize fails to allocate its internal structures.
Common situations: Two overlapping customization sessions trying to initialize MinHook in the same process; a previously crashed/partially cleaned-up session leaving MinHook initialized; low-memory conditions.
Related errors
- Failed to start the global hooking session
- throw ResultException(failure)
- throw PortableSettingsException(error)
- value name contains a NUL
- GetPrivateProfileString
AI-assisted analysis of ramensoftware/windhawk@61d99ed8e1 (2026-09-12).
Data as JSON: /api/errors/ae5ac7591a6a891e.
Report an issue: GitHub.
Appendix: source
Thrown at src/windhawk/engine/customization_session.cpp:218
LOG(L"AfterInit failed: %S", e.what());
}
}
CustomizationSession::~CustomizationSession() {
try {
m_modsManager.BeforeUninit();
} catch (const std::exception& e) {
LOG(L"BeforeUninit failed: %S", e.what());
}
}
#ifdef WH_HOOKING_ENGINE_MINHOOK
CustomizationSession::MinHookScopeInit::MinHookScopeInit(
MH_THREAD_FREEZE_METHOD freezeMethod) {
MH_STATUS status = MH_Initialize();
if (status != MH_OK) {
LOG(L"MH_Initialize failed with %d", status);
throw std::runtime_error("Failed to initialize MinHook");
}
MH_SetThreadFreezeMethod(freezeMethod);
#ifdef WH_HOOKING_ENGINE_MINHOOK_DETOURS
MH_SetBulkOperationMode(
/*continueOnError=*/TRUE, [](LPVOID pTarget, NTSTATUS detoursStatus) {
LOG(L"Hooking operation failed for %p with status 0x%08X", pTarget,
detoursStatus);
});
#endif
}
CustomizationSession::MinHookScopeInit::~MinHookScopeInit() {
MH_STATUS status = MH_Uninitialize();
if (status != MH_OK) {
LOG(L"MH_Uninitialize failed with status %d", status);
}View on GitHub (pinned to 61d99ed8e1)