{"record":{"id":"66f684ad1e80eeec","repo":"wailsapp/wails","slug":"invoke-variantinit-error","errorCode":null,"errorMessage":"Invoke VariantInit error.","messagePattern":"Invoke VariantInit error\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/pkg/w32/oleaut32.go","lineNumber":28,"sourceCode":"\t\"syscall\"\n\t\"unsafe\"\n)\n\nvar (\n\tmodoleaut32 = syscall.NewLazyDLL(\"oleaut32\")\n\n\tprocVariantInit        = modoleaut32.NewProc(\"VariantInit\")\n\tprocSysAllocString     = modoleaut32.NewProc(\"SysAllocString\")\n\tprocSysFreeString      = modoleaut32.NewProc(\"SysFreeString\")\n\tprocSysStringLen       = modoleaut32.NewProc(\"SysStringLen\")\n\tprocCreateDispTypeInfo = modoleaut32.NewProc(\"CreateDispTypeInfo\")\n\tprocCreateStdDispatch  = modoleaut32.NewProc(\"CreateStdDispatch\")\n)\n\nfunc VariantInit(v *VARIANT) {\n\thr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))\n\tif hr != 0 {\n\t\tpanic(\"Invoke VariantInit error.\")\n\t}\n\treturn\n}\n\nfunc SysAllocString(v string) (ss *int16) {\n\tpss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v))))\n\tss = (*int16)(unsafe.Pointer(pss))\n\treturn\n}\n\nfunc SysFreeString(v *int16) {\n\thr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v)))\n\tif hr != 0 {\n\t\tpanic(\"Invoke SysFreeString error.\")\n\t}\n\treturn\n}\n","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v3/pkg/w32/oleaut32.go#L10-L46","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the *VARIANT passed in points to a valid, zeroed struct allocated by the caller (var v VARIANT; VariantInit(&v))","If the panic is spurious, patch the wrapper to drop the hr check (VariantInit returns void) — upstream contribution candidate","Run with -race and review other unsafe.Pointer usage for corruption","Recover at the COM-call boundary so a bad call does not kill the app"],"exampleFix":"// before (wrapper in oleaut32.go)\nhr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))\nif hr != 0 { panic(\"Invoke VariantInit error.\") }\n\n// after - VariantInit is void and cannot fail\nprocVariantInit.Call(uintptr(unsafe.Pointer(v)))","handlingStrategy":"validation","validationCode":"if v == nil {\n    return errors.New(\"VariantInit: nil VARIANT pointer\")\n}\nw32.VariantInit(v)","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Printf(\"VariantInit panic (pointer invalid or spurious hr): %v\", r)\n    }\n}()","preventionTips":["Pass the address of a caller-owned, zeroed VARIANT","Know that VariantInit cannot fail in Win32 — a panic implies bad pointer or a wrapper bug","Report spurious panics upstream with Windows/Go versions"],"tags":["windows","com","variant","panic","wrapper-bug"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}