java-native-access/jna · error · com.sun.jna.platform.win32.COM.COMException
queryInterface: <formatMessageFromHR>
Error message
queryInterface: <formatMessageFromHR>
What it means
This COMException is raised by ProxyObject.queryInterface() when the underlying IDispatch.QueryInterface call returns a failed HRESULT. The Windows-format message for that HRESULT (via Kernel32Util.formatMessage) is appended, e.g. E_NOINTERFACE. It means the COM object does not support (or could not provide) the requested interface.
Source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java:502
throw new COMException(
"queryInterface: Interface must define a value for iid via the ComInterface annotation");
}
final IID iid = this.getIID(comInterfaceAnnotation);
final PointerByReference ppvObject = new PointerByReference();
HRESULT hr = ProxyObject.this.getRawDispatch().QueryInterface(new REFIID(iid), ppvObject);
if (WinNT.S_OK.equals(hr)) {
Dispatch dispatch = new Dispatch(ppvObject.getValue());
T t = this.factory.createProxy(comInterface, dispatch);
// QueryInterface returns a COM object pointer with a +1
// reference, we must drop one,
// Note: createProxy adds one;
int n = dispatch.Release();
return t;
} else {
String formatMessageFromHR = Kernel32Util.formatMessage(hr);
throw new COMException("queryInterface: " + formatMessageFromHR, hr);
}
} catch (RuntimeException e) {
// Do not rewrap COMException
if (e instanceof COMException) {
throw e;
} else {
throw new COMException("Error occured when trying to query for interface " + comInterface.getName(), e);
}
}
}
private IID getIID(ComInterface annotation) {
String iidStr = annotation.iid();
if (null != iidStr && !iidStr.isEmpty()) {
return new IID(iidStr);
} else {
throw new COMException("ComInterface must define a value for iid");
}View on GitHub (pinned to d036ad9781)
Solutions
- Check getHresult() — 0x80004002 (E_NOINTERFACE) means the object simply doesn't support it; guard that case
- Verify the @ComInterface iid against the server's type library
- Ensure COM apartment rules are respected (CoInitialize, same-thread or marshaled access)
- Catch COMException and fall back to another interface or a different API surface
Example fix
// before
Foo foo = proxy.queryInterface(Foo.class); // may E_NOINTERFACE
// after
try {
Foo foo = proxy.queryInterface(Foo.class);
} catch (COMException e) {
if (e.getHresult().intValue() == 0x80004002) { /* interface unsupported */ }
} Defensive patterns
Strategy: try-catch
Validate before calling
String iid = comInterface.getAnnotation(ComInterface.class).iid(); if (iid == null || iid.isEmpty()) throw new IllegalArgumentException("missing iid"); Type guard
boolean supported = false; try { proxy.queryInterface(Foo.class); supported = true; } catch (COMException e) { supported = e.getHresult().intValue() != 0x80004002; } Try / catch
try { Foo f = proxy.queryInterface(Foo.class); } catch (COMException e) { if (e.getHresult() != null && e.getHresult().intValue() == 0x80004002) { /* E_NOINTERFACE: handle optional absence */ } else { throw e; } } Prevention
- Treat E_NOINTERFACE as an expected outcome for optional interfaces
- Check server version supports the interface before QI
- Keep proxies on their owning thread
When it happens
Trigger: The COM object does not implement the requested interface (E_NOINTERFACE); the object was released or marshaled incorrectly; the IID is valid but unsupported by the running server version.
Common situations: Querying an optional interface the server version doesn't support; wrong GUID casing/GUID from a different type library; calling QI after the object left its apartment.
Related errors
- getUnknownId: <formatMessageFromHR>
- pDisp (IDispatch) parameter is null!
- Failed to enumerate results.
- Failed to create WbemLocator object.
- Could not set proxy blanket.
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/be841a323a9b3a16.
Report an issue: GitHub.