{"record":{"id":"ffb1d3df93346888","repo":"wailsapp/wails","slug":"drawmenubar-failed","errorCode":null,"errorMessage":"DrawMenuBar failed","messagePattern":"DrawMenuBar failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v2/internal/frontend/desktop/windows/winc/menu.go","lineNumber":130,"sourceCode":"\tif a.Checkable() {\n\t\tmii.FMask |= w32.MIIM_CHECKMARKS\n\t}\n\tif a.Checked() {\n\t\tmii.FState |= w32.MFS_CHECKED\n\t}\n\n\tif a.hSubMenu != 0 {\n\t\tmii.FMask |= w32.MIIM_SUBMENU\n\t\tmii.HSubMenu = a.hSubMenu\n\t}\n}\n\n// Show menu on the main window.\nfunc (m *Menu) Show() {\n\tinitialised = true\n\tupdateRadioGroups()\n\tif !w32.DrawMenuBar(m.hwnd) {\n\t\tpanic(\"DrawMenuBar failed\")\n\t}\n}\n\n// AddSubMenu returns item that is used as submenu to perform AddItem(s).\nfunc (m *Menu) AddSubMenu(text string) *MenuItem {\n\thSubMenu := w32.CreateMenu()\n\tif hSubMenu == 0 {\n\t\tpanic(\"failed CreateMenu\")\n\t}\n\treturn addMenuItem(m.hMenu, hSubMenu, text, Shortcut{}, nil, false)\n}\n\n// This method will iterate through the menu items, group radio items together, build a\n// quick access map and set the initial items\nfunc updateRadioGroups() {\n\n\tif !initialised {\n\t\treturn","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v2/internal/frontend/desktop/windows/winc/menu.go#L112-L148","documentation":"Menu.Show() redraws the menu bar of the main window with the Win32 DrawMenuBar call and panics if it returns false. DrawMenuBar fails when the stored window handle (m.hwnd) is invalid, zero, or belongs to an already-destroyed window, or when the call is made from outside the thread that owns the window.","triggerScenarios":"Calling Show() on a Menu whose target window was closed/destroyed (e.g. from an event handler after window teardown), calling Show() before the window handle was attached, or invoking it from a non-main goroutine on Windows.","commonSituations":"Rebuilding menus at runtime (e.g. localizing or dynamically updating the menu bar) and calling Show() during shutdown, or from a background goroutine that outlived the window.","solutions":["Only call Menu.Show() on the main/UI thread while the target window is alive","Re-create the menu against a valid, live window handle rather than reusing one bound to a destroyed window","Guard shutdown paths: cancel goroutines that may call Show() before the window is destroyed"],"exampleFix":"// before\n-go func() { menu.Show() }() // after window may be closed\n\n// after\napp.DispatchOnMainThread(func() {\n    if window.IsVisible() { // window still alive\n        menu.Show()\n    }\n})","handlingStrategy":"validation","validationCode":"// only show while the window handle is valid and we are on the UI thread\nif window != nil && window.Handle() != 0 && app.IsOnMainThread() {\n    menu.Show()\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Error(\"DrawMenuBar failed; window likely destroyed\", \"panic\", r)\n    }\n}()\nmenu.Show()","preventionTips":["Call Menu.Show() only from the main/UI thread","Cancel background goroutines that touch menus before window teardown","Rebind menus to a live window handle after window recreation"],"tags":["windows","win32","menu","ui-thread","panic"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}