{"record":{"id":"c312dc2987b9b2a2","repo":"dotnet/wpf","slug":"error-invalid-menu-handle-error-window-of-other-thread-1401","errorCode":"ERROR_INVALID_MENU_HANDLE..ERROR_WINDOW_OF_OTHER_THREAD (1401-1408)","errorMessage":"ElementNotAvailableException","messagePattern":"ElementNotAvailableException","errorType":"exception","errorClass":"ElementNotAvailableException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/Misc.cs","lineNumber":1682,"sourceCode":"        internal static void ThrowWin32ExceptionsIfError(int errorCode)\n        {\n            switch (errorCode)\n            {\n                case 0:     //    0 ERROR_SUCCESS                   The operation completed successfully.\n                    // The error code indicates that there is no error, so do not throw an exception.\n                    break;\n\n                case 6:     //    6 ERROR_INVALID_HANDLE            The handle is invalid.\n                case 1400:  // 1400 ERROR_INVALID_WINDOW_HANDLE     Invalid window handle.\n                case 1401:  // 1401 ERROR_INVALID_MENU_HANDLE       Invalid menu handle.\n                case 1402:  // 1402 ERROR_INVALID_CURSOR_HANDLE     Invalid cursor handle.\n                case 1403:  // 1403 ERROR_INVALID_ACCEL_HANDLE      Invalid accelerator table handle.\n                case 1404:  // 1404 ERROR_INVALID_HOOK_HANDLE       Invalid hook handle.\n                case 1405:  // 1405 ERROR_INVALID_DWP_HANDLE        Invalid handle to a multiple-window position structure.\n                case 1406:  // 1406 ERROR_TLW_WITH_WSCHILD          Cannot create a top-level child window.\n                case 1407:  // 1407 ERROR_CANNOT_FIND_WND_CLASS     Cannot find window class.\n                case 1408:  // 1408 ERROR_WINDOW_OF_OTHER_THREAD    Invalid window; it belongs to other thread.\n                    throw new ElementNotAvailableException();\n\n                // We're getting this in AMD64 when calling RealGetWindowClass; adding this code\n                // to allow the DRTs to pass while we continue investigation.\n                case 87:    //   87 ERROR_INVALID_PARAMETER\n                    throw new ElementNotAvailableException();\n\n                case 8:     //    8 ERROR_NOT_ENOUGH_MEMORY         Not enough storage is available to process this command.\n                case 14:    //   14 ERROR_OUTOFMEMORY               Not enough storage is available to complete this operation.\n                    throw new OutOfMemoryException();\n\n                case 998:   //  998 ERROR_NOACCESS                  Invalid access to memory location.\n                case 5:     //    5 ERROR_ACCESS_DENIED\n                    throw new InvalidOperationException();\n\n                case 121:   //  121 ERROR_SEM_TIMEOUT               The semaphore timeout period has expired.\n                case 258:   //  258 WAIT_TIMEOUT                    The wait operation timed out.\n                case 1053:  // 1053 ERROR_SERVICE_REQUEST_TIMEOUT   The service did not respond to the start or control request in a timely fashion.\n                case 1460:  // 1460 ERROR_TIMEOUT                   This operation returned because the timeout period expired.","sourceCodeStart":1664,"sourceCodeEnd":1700,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/Misc.cs#L1664-L1700","documentation":"Misc's Win32 error-code mapper throws ElementNotAvailableException for system error codes 1400-1408, including ERROR_INVALID_MENU_HANDLE (1401) through ERROR_WINDOW_OF_OTHER_THREAD (1408). These codes indicate the window/menu/hook resource the call targeted is invalid or belongs to another thread, so the corresponding UIA element is treated as no longer available.","triggerScenarios":"A Win32 call made by the proxy fails with GetLastError in the 1400-1408 range — invalid window handles, invalid menu handles (1401), or a window owned by another thread (1408), typically during RealGetWindowClass, menu queries, or cross-thread window operations.","commonSituations":"Menu handles going stale after a menu closed; cross-thread access to windows of a UI thread that is busy or gone; x64-specific behavior seen with RealGetWindowClass.","solutions":["Re-acquire the element/handle — the underlying Win32 resource has gone stale","Ensure UIA calls to another app's windows go through the proper cross-process automation path, not raw handles","Catch ElementNotAvailableException around pattern/property calls and re-walk the tree","Check that menus/popups are still open before querying their handles"],"exampleFix":"// before\nvar className = Misc.RealGetWindowClass(hwnd); // throws on 1401-1408\n// after\ntry\n{\n    var className = Misc.RealGetWindowClass(hwnd);\n}\ncatch (ElementNotAvailableException)\n{\n    // invalid menu/window handle or other-thread window: re-acquire element\n    hwnd = RefreshHandle();\n}","handlingStrategy":"try-catch","validationCode":"// Invalidate stale handles before use:\nif (!IsWindow(hwnd) || !IsMenu(hMenu)) { ReacquireHandles(); }","typeGuard":null,"tryCatchPattern":"try { QueryWindow(hwnd); } catch (ElementNotAvailableException) { ReacquireHandles(); Retry(); }","preventionTips":["Re-fetch menu/hook/window handles after every UI state change","Avoid raw cross-thread window manipulation; use the automation API","Log the exact Win32 error code to distinguish 1400-1408 variants","Verify popup/menu windows still exist before querying them"],"tags":["ui-automation","win32-error","stale-handle","menu-handle"],"backgroundTag":"resource-not-found","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"}