{"record":{"id":"30dc3fe6e9284fb5","repo":"wailsapp/wails","slug":"failed-createmenu-30dc3f","errorCode":null,"errorMessage":"failed CreateMenu","messagePattern":"failed CreateMenu","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v2/internal/frontend/desktop/windows/winc/menu.go","lineNumber":62,"sourceCode":"\n\tcheckable bool\n\tchecked   bool\n\tisRadio   bool\n\n\tid uint16\n\n\tonClick EventManager\n}\n\ntype RadioGroup struct {\n\tmembers []*MenuItem\n\thwnd    w32.HWND\n}\n\nfunc NewContextMenu() *MenuItem {\n\thMenu := w32.CreatePopupMenu()\n\tif hMenu == 0 {\n\t\tpanic(\"failed CreateMenu\")\n\t}\n\n\titem := &MenuItem{\n\t\thMenu:    hMenu,\n\t\thSubMenu: hMenu,\n\t}\n\treturn item\n}\n\nfunc (m *Menu) Dispose() {\n\tif m.hMenu != 0 {\n\t\tw32.DestroyMenu(m.hMenu)\n\t\tm.hMenu = 0\n\t}\n}\n\nfunc (m *Menu) IsDisposed() bool {\n\treturn m.hMenu == 0","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v2/internal/frontend/desktop/windows/winc/menu.go#L44-L80","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nfunc (a *App) ShowContextMenu() {\n    menu := winc.NewContextMenu() // leaked every invocation\n    ...\n}\n\n// after\n// create once in setup, attach via SetContextMenu, reuse; on shutdown:\n// menu.Dispose()","handlingStrategy":"validation","validationCode":"// preflight: ensure you are not leaking menus before creating more\nif getUserObjectCountsyscall() > warningThreshold { // via GetGuiResources GetCurrentProcess, GR_USEROBJECTS\n    disposeAndRebuildContextMenu()\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Error(\"context menu creation failed\", \"panic\", r)\n        // fall back to a previously built shared menu or skip the popup\n    }\n}()\nmenu := winc.NewContextMenu()","preventionTips":["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"],"tags":["windows","win32","menu","resource-leak","panic"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}