wailsapp/wails · error
DrawMenuBar failed
Error message
DrawMenuBar failed
What it means
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.
Source
Thrown at v2/internal/frontend/desktop/windows/winc/menu.go:130
if a.Checkable() {
mii.FMask |= w32.MIIM_CHECKMARKS
}
if a.Checked() {
mii.FState |= w32.MFS_CHECKED
}
if a.hSubMenu != 0 {
mii.FMask |= w32.MIIM_SUBMENU
mii.HSubMenu = a.hSubMenu
}
}
// Show menu on the main window.
func (m *Menu) Show() {
initialised = true
updateRadioGroups()
if !w32.DrawMenuBar(m.hwnd) {
panic("DrawMenuBar failed")
}
}
// AddSubMenu returns item that is used as submenu to perform AddItem(s).
func (m *Menu) AddSubMenu(text string) *MenuItem {
hSubMenu := w32.CreateMenu()
if hSubMenu == 0 {
panic("failed CreateMenu")
}
return addMenuItem(m.hMenu, hSubMenu, text, Shortcut{}, nil, false)
}
// This method will iterate through the menu items, group radio items together, build a
// quick access map and set the initial items
func updateRadioGroups() {
if !initialised {
returnView on GitHub (pinned to 0e754b1b40)
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
Example fix
// before
-go func() { menu.Show() }() // after window may be closed
// after
app.DispatchOnMainThread(func() {
if window.IsVisible() { // window still alive
menu.Show()
}
}) Defensive patterns
Strategy: validation
Validate before calling
// only show while the window handle is valid and we are on the UI thread
if window != nil && window.Handle() != 0 && app.IsOnMainThread() {
menu.Show()
} Try / catch
defer func() {
if r := recover(); r != nil {
log.Error("DrawMenuBar failed; window likely destroyed", "panic", r)
}
}()
menu.Show() Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed CreateMenu
- RadioGroup.MenuID: item not found:
- invalid stream batch acknowledgement
- no element matches selector: ' + target.selector
- failed CreateMenu
AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15).
Data as JSON: /api/errors/ffb1d3df93346888.
Report an issue: GitHub.