wailsapp/wails · error
failed CreateMenu
Error message
failed CreateMenu
What it means
NewContextMenu calls the Win32 API CreatePopupMenu and panics when it returns a NULL handle (0). A NULL handle means Windows refused to allocate a new menu, which almost always indicates resource exhaustion (GDI/user handle leak) or that the call happened from the wrong thread/state. This is wails' win32 menu wrapper for right-click context menus on Windows.
Source
Thrown at v2/internal/frontend/desktop/windows/winc/menu.go:62
checkable bool
checked bool
isRadio bool
id uint16
onClick EventManager
}
type RadioGroup struct {
members []*MenuItem
hwnd w32.HWND
}
func NewContextMenu() *MenuItem {
hMenu := w32.CreatePopupMenu()
if hMenu == 0 {
panic("failed CreateMenu")
}
item := &MenuItem{
hMenu: hMenu,
hSubMenu: hMenu,
}
return item
}
func (m *Menu) Dispose() {
if m.hMenu != 0 {
w32.DestroyMenu(m.hMenu)
m.hMenu = 0
}
}
func (m *Menu) IsDisposed() bool {
return m.hMenu == 0View on GitHub (pinned to 0e754b1b40)
Solutions
- Build the context menu once and reuse it, updating items instead of recreating it on every popup
- Call Dispose() (w32.DestroyMenu) on every MenuItem created with NewContextMenu when you are done with it
- Check the process USER handle count in Task Manager / Process Explorer to confirm a leak
- If creation genuinely must be dynamic, wrap the call in a recover() and degrade gracefully
Example fix
// before
func (a *App) ShowContextMenu() {
menu := winc.NewContextMenu() // leaked every invocation
...
}
// after
// create once in setup, attach via SetContextMenu, reuse; on shutdown:
// menu.Dispose() Defensive patterns
Strategy: validation
Validate before calling
// preflight: ensure you are not leaking menus before creating more
if getUserObjectCountsyscall() > warningThreshold { // via GetGuiResources GetCurrentProcess, GR_USEROBJECTS
disposeAndRebuildContextMenu()
} Try / catch
defer func() {
if r := recover(); r != nil {
log.Error("context menu creation failed", "panic", r)
// fall back to a previously built shared menu or skip the popup
}
}()
menu := winc.NewContextMenu() Prevention
- Create the context menu once and mutate its items per invocation
- Always pair NewContextMenu with a deferred or shutdown Dispose()
- Track USER handle count in long-running Windows apps
When it happens
Trigger: Creating many context menus via NewContextMenu in a loop without ever calling Dispose(), so the process exhausts its USER object quota (default ~10k handles); or calling it after the window/thread teardown has begun.
Common situations: An app that builds a fresh context menu on every right-click (e.g. per-tree-node menus regenerated on each show) instead of reusing one; long-running apps on Windows whose handle count creeps up until CreatePopupMenu starts failing.
Related errors
- failed CreateMenu
- DrawMenuBar failed
- RadioGroup.MenuID: item not found:
- invalid stream batch acknowledgement
- no element matches selector: ' + target.selector
AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15).
Data as JSON: /api/errors/30dc3fe6e9284fb5.
Report an issue: GitHub.