wailsapp/wails · error

missing icon with icon ID: %d

Error message

missing icon with icon ID: %d

What it means

Button.SetResIcon tries to load an icon by numeric resource ID from the executable's resources via NewIconFromResource(GetAppInstance(), iconID); if the lookup fails it panics with the missing ID. This means the .exe (or the module returned by GetAppInstance) has no icon resource with that numeric ID — common when resources live in a linked .syso/.rc file that was not built in, or the ID was taken from a header that does not match the compiled resource script.

Source

Thrown at v2/internal/frontend/desktop/windows/winc/buttons.go:63

func (bt *Button) SetChecked(checked bool) {
	wparam := w32.BST_CHECKED
	if !checked {
		wparam = w32.BST_UNCHECKED
	}
	w32.SendMessage(bt.hwnd, w32.BM_SETCHECK, uintptr(wparam), 0)
}

// SetIcon sets icon on the button. Recommended icons are 32x32 with 32bit color depth.
func (bt *Button) SetIcon(ico *Icon) {
	w32.SendMessage(bt.hwnd, w32.BM_SETIMAGE, w32.IMAGE_ICON, uintptr(ico.handle))
}

func (bt *Button) SetResIcon(iconID uint16) {
	if ico, err := NewIconFromResource(GetAppInstance(), iconID); err == nil {
		bt.SetIcon(ico)
		return
	}
	panic(fmt.Sprintf("missing icon with icon ID: %d", iconID))
}

type PushButton struct {
	Button
}

func NewPushButton(parent Controller) *PushButton {
	pb := new(PushButton)

	pb.InitControl("BUTTON", parent, 0, w32.BS_PUSHBUTTON|w32.WS_TABSTOP|w32.WS_VISIBLE|w32.WS_CHILD)
	RegMsgHandler(pb)

	pb.SetFont(DefaultFont)
	pb.SetText("Button")
	pb.SetSize(100, 22)

	return pb
}

View on GitHub (pinned to 0e754b1b40)

Solutions

  1. Inspect the built executable's resources (Resource Hacker, or `windres`/`go-winres` dump) and confirm an icon exists with the exact numeric ID passed to SetResIcon
  2. Keep resource IDs in a single shared resource.h and regenerate the .syso whenever IDs change: `go-winres simply --icon-id=<id>` (or windres) then rebuild
  3. Load icons by file path or embedded bytes instead (NewIconFromResource is module-based): use image.NewIconFromFile / embed the icon and create it from an HICON you control
  4. Guard with a runtime lookup before calling SetResIcon (see validation code) so a missing icon degrades gracefully instead of panicking

Example fix

// before
btn.SetResIcon(101) // panics if exe has no icon resource 101

// after
if _, err := winc.NewIconFromResource(winc.GetAppInstance(), 101); err == nil {
    btn.SetResIcon(101)
} else {
    ico, _ := winc.NewIconFromFile("assets/button.ico")
    if ico != nil { btn.SetIcon(ico) }
}
Defensive patterns

Strategy: validation

Validate before calling

func resIconExists(id uint16) bool {
    _, err := winc.NewIconFromResource(winc.GetAppInstance(), id)
    return err == nil
}

if resIconExists(101) {
    btn.SetResIcon(101)
} else {
    if ico, err := winc.NewIconFromFile("assets/fallback.ico"); err == nil {
        btn.SetIcon(ico)
    }
}

Prevention

When it happens

Trigger: Calling button.SetResIcon(n) where n is not defined as an ICON resource in the application's .rc/.syso; IDs shifted because the .rc auto-numbering (or a resource header like resource.h) changed; the resource was embedded as a string name instead of a numeric ID.

Common situations: Wails v2 Windows apps embedding icons via windres/go-winres .syso files where the generated IDs don't match; porting WinForms-style code that used MAKEINTRESOURCE IDs from a different project; CI builds stripping resources.

Related errors


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