{"record":{"id":"831c3f22665d4233","repo":"wailsapp/wails","slug":"invoke-qieryinterface-error","errorCode":null,"errorMessage":"Invoke QieryInterface error.","messagePattern":"Invoke QieryInterface error\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/pkg/w32/utils.go","lineNumber":101,"sourceCode":"\treturn int32(ret)\n}\n\nfunc ComRelease(unknown *IUnknown) int32 {\n\tret, _, _ := syscall.SyscallN(uintptr(unknown.Vtbl.Release),\n\t\tuintptr(unsafe.Pointer(unknown)),\n\t\t0,\n\t\t0)\n\treturn int32(ret)\n}\n\nfunc ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch {\n\tvar disp *IDispatch\n\thr, _, _ := syscall.SyscallN(uintptr(unknown.Vtbl.QueryInterface),\n\t\tuintptr(unsafe.Pointer(unknown)),\n\t\tuintptr(unsafe.Pointer(id)),\n\t\tuintptr(unsafe.Pointer(&disp)))\n\tif hr != 0 {\n\t\tpanic(\"Invoke QieryInterface error.\")\n\t}\n\treturn disp\n}\n\nfunc ComGetIDsOfName(disp *IDispatch, names []string) []int32 {\n\twnames := make([]*uint16, len(names))\n\tdispid := make([]int32, len(names))\n\tfor i := 0; i < len(names); i++ {\n\t\twnames[i] = syscall.StringToUTF16Ptr(names[i])\n\t}\n\thr, _, _ := syscall.SyscallN(disp.lpVtbl.pGetIDsOfNames,\n\t\tuintptr(unsafe.Pointer(disp)),\n\t\tuintptr(unsafe.Pointer(IID_NULL)),\n\t\tuintptr(unsafe.Pointer(&wnames[0])),\n\t\tuintptr(len(names)),\n\t\tuintptr(GetUserDefaultLCID()),\n\t\tuintptr(unsafe.Pointer(&dispid[0])))\n\tif hr != 0 {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v3/pkg/w32/utils.go#L83-L119","documentation":"ComQueryInterface calls IUnknown::QueryInterface on a raw COM pointer via the vtable and panics when the HRESULT is non-zero (message has a typo: 'QieryInterface'). QueryInterface fails with E_NOINTERFACE when the object does not implement the requested IID, or E_POINTER when arguments are bad — the wrapper flattens both into a panic and returns no error.","triggerScenarios":"Querying an IUnknown for IID_IDispatch when the COM class is not automation-compatible; calling with a nil *IUnknown (crash before the hr check); passing a GUID pointer that does not match the interface actually implemented; using a pointer whose object was already Release()d.","commonSituations":"Wails Windows integration code obtaining dispatch interfaces for shell/OLE objects (e.g. IShellLink, file dialogs) where an interface is missing on older Windows or on a stub object; lifetime bugs where the object was freed before the QI.","solutions":["Confirm the target object actually implements the interface you request (check the COM class documentation / verify the IID constant)","Ensure the source pointer is alive: do not QueryInterface after the final Release","Prefer an error-returning QI helper (check hr for E_NOINTERFACE instead of panicking) — contribute a non-panicking variant upstream","Recover around the call and treat failure as 'interface not supported'"],"exampleFix":"// before\ndisp := w32.ComQueryInterface(unknown, &w32.IID_IDispatch) // panics on E_NOINTERFACE\n\n// after\nfunc queryInterface(u *w32.IUnknown, id *w32.GUID) (*w32.IDispatch, error) {\n    defer func() {\n        if r := recover(); r != nil {\n            // rethrow as error via named return\n        }\n    }()\n    return w32.ComQueryInterface(u, id), nil\n}","handlingStrategy":"try-catch","validationCode":"if unknown == nil || unknown.Vtbl.QueryInterface == 0 {\n    return nil, errors.New(\"ComQueryInterface: nil COM pointer\")\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        err = fmt.Errorf(\"QueryInterface failed (E_NOINTERFACE or bad pointer): %v\", r)\n    }\n}()\ndisp = w32.ComQueryInterface(unknown, id)","preventionTips":["Verify the IID is implemented by the target class before querying","Keep the source object alive (outstanding AddRef) across the call","Prefer error-returning QI wrappers in new code"],"tags":["windows","com","queryinterface","panic"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}