wailsapp/wails · error

Invoke VariantInit error.

Error message

Invoke VariantInit error.

What it means

The wrapper around VariantInit panicked because the syscall returned a non-zero value. In the real Win32 API VariantInit is a void function that cannot fail; the Go code reads the return register anyway, so a non-zero value means either a nil/garbage VARIANT pointer was passed or the register simply held leftover data — the check itself is unreliable.

Source

Thrown at v3/pkg/w32/oleaut32.go:28

	"syscall"
	"unsafe"
)

var (
	modoleaut32 = syscall.NewLazyDLL("oleaut32")

	procVariantInit        = modoleaut32.NewProc("VariantInit")
	procSysAllocString     = modoleaut32.NewProc("SysAllocString")
	procSysFreeString      = modoleaut32.NewProc("SysFreeString")
	procSysStringLen       = modoleaut32.NewProc("SysStringLen")
	procCreateDispTypeInfo = modoleaut32.NewProc("CreateDispTypeInfo")
	procCreateStdDispatch  = modoleaut32.NewProc("CreateStdDispatch")
)

func VariantInit(v *VARIANT) {
	hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))
	if hr != 0 {
		panic("Invoke VariantInit error.")
	}
	return
}

func SysAllocString(v string) (ss *int16) {
	pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v))))
	ss = (*int16)(unsafe.Pointer(pss))
	return
}

func SysFreeString(v *int16) {
	hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v)))
	if hr != 0 {
		panic("Invoke SysFreeString error.")
	}
	return
}

View on GitHub (pinned to 0e754b1b40)

Solutions

  1. Ensure the *VARIANT passed in points to a valid, zeroed struct allocated by the caller (var v VARIANT; VariantInit(&v))
  2. If the panic is spurious, patch the wrapper to drop the hr check (VariantInit returns void) — upstream contribution candidate
  3. Run with -race and review other unsafe.Pointer usage for corruption
  4. Recover at the COM-call boundary so a bad call does not kill the app

Example fix

// before (wrapper in oleaut32.go)
hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))
if hr != 0 { panic("Invoke VariantInit error.") }

// after - VariantInit is void and cannot fail
procVariantInit.Call(uintptr(unsafe.Pointer(v)))
Defensive patterns

Strategy: validation

Validate before calling

if v == nil {
    return errors.New("VariantInit: nil VARIANT pointer")
}
w32.VariantInit(v)

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Printf("VariantInit panic (pointer invalid or spurious hr): %v", r)
    }
}()

Prevention

When it happens

Trigger: Passing a nil *VARIANT or one pointing to freed memory to w32.VariantInit; heap corruption from earlier unsafe code; occasionally a spurious panic purely from the undefined return register on certain Windows versions.

Common situations: COM automation code (ComInvoke, IDispatch calls) where the result VARIANT lives in a frame that was already unwound; porting go-ole style code where VariantInit never returns a value; rarely, false positives that disappear after a Go or Windows update.

Related errors


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