java-native-access/jna · error · com.sun.jna.platform.win32.COM.COMException
getUnknownId: <formatMessageFromHR>
Error message
getUnknownId: <formatMessageFromHR>
What it means
This COMException is thrown by ProxyObject.getUnknownId() when the underlying COM call to obtain the IUnknown identifier fails with a non-zero HRESULT. The library appends the human-readable Windows error message (via Kernel32Util.formatMessage) to help identify the exact COM failure. It signals that the proxy could not retrieve or negotiate the IUnknown pointer for the wrapped COM object.
Source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java:120
try {
final PointerByReference ppvObject = new PointerByReference();
Thread current = Thread.currentThread();
String tn = current.getName();
IID iid = com.sun.jna.platform.win32.COM.IUnknown.IID_IUNKNOWN;
HRESULT hr = ProxyObject.this.getRawDispatch().QueryInterface(new REFIID(iid), ppvObject);
if (WinNT.S_OK.equals(hr)) {
Dispatch dispatch = new Dispatch(ppvObject.getValue());
this.unknownId = Pointer.nativeValue(dispatch.getPointer());
// QueryInterface returns a COM object pointer with a +1
// reference, we must drop one,
// Note: createProxy adds one;
int n = dispatch.Release();
} else {
String formatMessageFromHR = Kernel32Util.formatMessage(hr);
throw new COMException("getUnknownId: " + formatMessageFromHR, hr);
}
} catch (RuntimeException e) {
// Do not rewrap COMException
if (e instanceof COMException) {
throw e;
} else {
throw new COMException("Error occured when trying get Unknown Id ", e);
}
}
}
return this.unknownId;
}
@Override
protected void finalize() throws Throwable {
this.dispose();
super.finalize();
}View on GitHub (pinned to d036ad9781)
Solutions
- Ensure COM is initialized on the calling thread (COMUtils.comIsInitialized) and use the object from the thread/apartment that created it
- Wrap calls in the handler utilities provided (com.sun.jna.platform.win32.COM.util.HandlerUtil) which marshal calls to the creating thread
- Catch COMException and inspect getHresult() to identify the specific Windows error code
- Release and re-create the proxy if the underlying COM object was freed
Example fix
// before
Object id = proxy.getUnknownId(); // throws if called off-apartment
// after
if (COMUtils.comIsInitialized()) {
Object id = HandlerUtil.getObjectIdentity(handler); // marshals to owner thread
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!COMUtils.comIsInitialized()) { throw new IllegalStateException("COM not initialized on this thread"); } Type guard
boolean usable = proxy != null && COMUtils.comIsInitialized();
Try / catch
try { Object id = proxy.getUnknownId(); } catch (COMException e) { LOG.error("getUnknownId failed hr=0x" + Integer.toHexString(e.getHresult().intValue()), e); } Prevention
- Initialize COM per-thread with ComFactory/COMUtils before touching proxies
- Keep proxy usage on the thread that created it or use HandlerUtil marshaling
- Do not release the underlying dispatch while the proxy is alive
When it happens
Trigger: The raw dispatch.QueryInterface(IUnknown) or related COM call returns a failed HRESULT; the COM object has been released from another thread (RCW released) or its apartment (STA/MTA) requirements are violated.
Common situations: Calling proxy methods from a thread that is not the COM apartment owner; the underlying COM server crashed or released the object; cross-apartment marshaling without proper initialization (CoInitialize missing).
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Error occured when trying get Unknown Id
- queryInterface: <formatMessageFromHR>
- RuntimeException(hr.toString())
- StringFromGUID2
- pDisp (IDispatch) parameter is null!
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/be2038e6bb62d7a2.
Report an issue: GitHub.