wailsapp/wails · error

Invoke QieryInterface error.

Error message

Invoke QieryInterface error.

What it means

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.

Source

Thrown at v3/pkg/w32/utils.go:101

	return int32(ret)
}

func ComRelease(unknown *IUnknown) int32 {
	ret, _, _ := syscall.SyscallN(uintptr(unknown.Vtbl.Release),
		uintptr(unsafe.Pointer(unknown)),
		0,
		0)
	return int32(ret)
}

func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch {
	var disp *IDispatch
	hr, _, _ := syscall.SyscallN(uintptr(unknown.Vtbl.QueryInterface),
		uintptr(unsafe.Pointer(unknown)),
		uintptr(unsafe.Pointer(id)),
		uintptr(unsafe.Pointer(&disp)))
	if hr != 0 {
		panic("Invoke QieryInterface error.")
	}
	return disp
}

func ComGetIDsOfName(disp *IDispatch, names []string) []int32 {
	wnames := make([]*uint16, len(names))
	dispid := make([]int32, len(names))
	for i := 0; i < len(names); i++ {
		wnames[i] = syscall.StringToUTF16Ptr(names[i])
	}
	hr, _, _ := syscall.SyscallN(disp.lpVtbl.pGetIDsOfNames,
		uintptr(unsafe.Pointer(disp)),
		uintptr(unsafe.Pointer(IID_NULL)),
		uintptr(unsafe.Pointer(&wnames[0])),
		uintptr(len(names)),
		uintptr(GetUserDefaultLCID()),
		uintptr(unsafe.Pointer(&dispid[0])))
	if hr != 0 {

View on GitHub (pinned to 0e754b1b40)

Solutions

  1. Confirm the target object actually implements the interface you request (check the COM class documentation / verify the IID constant)
  2. Ensure the source pointer is alive: do not QueryInterface after the final Release
  3. Prefer an error-returning QI helper (check hr for E_NOINTERFACE instead of panicking) — contribute a non-panicking variant upstream
  4. Recover around the call and treat failure as 'interface not supported'

Example fix

// before
disp := w32.ComQueryInterface(unknown, &w32.IID_IDispatch) // panics on E_NOINTERFACE

// after
func queryInterface(u *w32.IUnknown, id *w32.GUID) (*w32.IDispatch, error) {
    defer func() {
        if r := recover(); r != nil {
            // rethrow as error via named return
        }
    }()
    return w32.ComQueryInterface(u, id), nil
}
Defensive patterns

Strategy: try-catch

Validate before calling

if unknown == nil || unknown.Vtbl.QueryInterface == 0 {
    return nil, errors.New("ComQueryInterface: nil COM pointer")
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        err = fmt.Errorf("QueryInterface failed (E_NOINTERFACE or bad pointer): %v", r)
    }
}()
disp = w32.ComQueryInterface(unknown, id)

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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