wailsapp/wails · error

Error occurred in App.Init

Error message

Error occurred in App.Init

What it means

CoCreateInstance panics with 'E_UNEXPECTED' in the w32 wrapper when the COM activation hit an unforeseeable internal error. Distinct from class-not-registered or interface-not-supported (which are returned as HRESULTs, not panicked), E_UNEXPECTED here typically means COM state on the thread is broken: COM not initialized on that thread, a prior CoUninitialize imbalance, or the apartment was torn down out from under the call.

Source

Thrown at v2/internal/frontend/desktop/windows/winc/app.go:27

import (
	"runtime"
	"unsafe"

	"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
)

var (
	// resource compilation tool assigns app.ico ID of 3
	// rsrc -manifest app.manifest -ico app.ico -o rsrc.syso
	AppIconID = 3
)

func init() {
	runtime.LockOSThread()

	gAppInstance = w32.GetModuleHandle("")
	if gAppInstance == 0 {
		panic("Error occurred in App.Init")
	}

	// Initialize the common controls
	var initCtrls w32.INITCOMMONCONTROLSEX
	initCtrls.DwSize = uint32(unsafe.Sizeof(initCtrls))
	initCtrls.DwICC =
		w32.ICC_LISTVIEW_CLASSES | w32.ICC_PROGRESS_CLASS | w32.ICC_TAB_CLASSES |
			w32.ICC_TREEVIEW_CLASSES | w32.ICC_BAR_CLASSES

	w32.InitCommonControlsEx(&initCtrls)
}

// SetAppIcon sets resource icon ID for the apps windows.
func SetAppIcon(appIconID int) {
	AppIconID = appIconID
}

func GetAppInstance() w32.HINSTANCE {

View on GitHub (pinned to 0e754b1b40)

Solutions

  1. runtime.LockOSThread() on any goroutine that calls CoCreateInstance, and initialize COM on that same thread first.
  2. Centralize COM usage in one dedicated thread (actor-style channel loop) that does init once.
  3. Check other HRESULTs are being handled first — if REGDB_E_CLASSNOTREGISTERED paths work but this fires intermittently, it is a threading issue.
  4. Ensure CoUninitialize only runs after all activations on that thread have completed.

Example fix

// before
func showDialog(){
	go func(){
		// OS thread not locked, COM not initialized here
		CoCreateInstance(&clsid, CLSCTX_ALL, &riid, ppv) // E_UNEXPECTED panic
	}()
}

// after
func showDialog(){
	go func(){
		runtime.LockOSThread()
		defer runtime.UnlockOSThread()
		CoInitializeEx(COINIT_APARTMENTTHREADED)
		defer CoUninitialize()
		CoCreateInstance(&clsid, CLSCTX_ALL, &riid, ppv)
	}()
}
Defensive patterns

Strategy: validation

Validate before calling

func comReadyOnThisThread() bool {
	// COM must have been initialized on this exact OS thread;
	// enforce by construction: always pair LockOSThread with CoInitializeEx.
	return comInitDone 
}

Try / catch

defer func() {
	if r := recover(); r != nil {
		if msg, _ := r.(string); strings.Contains(msg, "E_UNEXPECTED") {
			err = fmt.Errorf("com activation on uninit/thread-broken thread: %v", r)
			return
		}
		panic(r)
	}
}()
CoCreateInstance(clsid, w32.CLSCTX_ALL, riid, ppv)

Prevention

When it happens

Trigger: Calling CoCreateInstance from a goroutine whose OS thread never called CoInitializeEx (COM requires per-thread init); the initializing goroutine unlocking its OS thread so calls land on different, uninitialized threads; CoUninitialize running on the thread while activations are in flight.

Common situations: Go-specific: forgetting runtime.LockOSThread before using COM-heavy features, so the scheduler migrates the call onto a fresh thread without COM; shared singletons in Wails apps (taskbar progress, file dialogs) whose init ran on a different goroutine than the use site.

Related errors


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