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 {
		return

View on GitHub (pinned to 0e754b1b40)

Solutions

  1. Only call Menu.Show() on the main/UI thread while the target window is alive
  2. Re-create the menu against a valid, live window handle rather than reusing one bound to a destroyed window
  3. 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

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


AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15). Data as JSON: /api/errors/ffb1d3df93346888. Report an issue: GitHub.