wailsapp/wails · error

RadioGroup.MenuID: item not found:

Error message

RadioGroup.MenuID: item not found:

What it means

RadioGroup.MenuID panics when asked for the Win32 command ID of a radio menu item that is not a member of that radio group. It is called from Win32Menu.updateRadioGroup (popupmenu_windows.go:425), which runs whenever a checked radio item is updated (UpdateMenuItem / SetChecked). The panic signals an internal bookkeeping mismatch: the item was checked before the popup menu registered its radio groups during build, or the group map was rebuilt while the item reference went stale.

Solutions

  1. Only SetChecked(true) on radio items after the popup/context menu has been opened at least once, or drive checked state via NewMenuItemRadio(label, true) at construction
  2. Re-create menu items rather than reusing stale pointers across menu rebuilds
  3. If it reproduces with fresh pointers and a shown menu, file a bug at wailsapp/wails with a minimal repro (popup menu + radio group)

Example fix

// before (panics if menu not yet shown / stale pointer)
myRadioItem.SetChecked(true)

// after (set initial state at construction, update only after menu is shown)
myRadioItem := application.NewMenuItemRadio("Option A", true)
// later, after the context menu has been displayed:
myRadioItem.SetChecked(true)
Defensive patterns

Strategy: try-catch

Try / catch

func safeSetChecked(item *application.MenuItem, checked bool) {
	defer func() {
		if r := recover(); r != nil {
			log.Printf("SetChecked on radio item before menu registration: %v", r)
		}
	}()
	item.SetChecked(checked)
}

Prevention

When it happens

Trigger: On Windows, calling MenuItem.SetChecked(true) on a NewMenuItemRadio item before the containing popup/context menu has been shown (radioGroups not yet populated), or after the menu was rebuilt so the *MenuItem in the map no longer equals the item being updated (pointer identity comparison fails).

Common situations: Toggling radio items from bindings right after startup; updating radio state from a background goroutine while the context menu is being rebuilt; reusing MenuItem pointers across menu rebuilds.

Related errors


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

Appendix: source

Thrown at v3/pkg/application/popupmenu_windows.go:43

func (r *RadioGroup) Add(id int, item *MenuItem) {
	*r = append(*r, &RadioGroupMember{
		ID:       id,
		MenuItem: item,
	})
}

func (r *RadioGroup) Bounds() (int, int) {
	p := *r
	return p[0].ID, p[len(p)-1].ID
}

func (r *RadioGroup) MenuID(item *MenuItem) int {
	for _, member := range *r {
		if member.MenuItem == item {
			return member.ID
		}
	}
	panic("RadioGroup.MenuID: item not found:")
}

type Win32Menu struct {
	isPopup       bool
	menu          w32.HMENU
	parentWindow  *windowsWebviewWindow
	parent        w32.HWND
	menuMapping   map[int]*MenuItem
	checkboxItems map[*MenuItem][]int
	radioGroups   map[*MenuItem][]*RadioGroup
	menuData      *Menu
	currentMenuID int
	onMenuClose   func()
	onMenuOpen    func()
	isShowing     atomic.Bool // guards against concurrent TrackPopupMenuEx calls

	// bitmaps tracks HBITMAP handles allocated by SetMenuIcons during
	// buildMenu so they can be released when the menu is rebuilt or

View on GitHub (pinned to 0e754b1b40)