java-native-access/jna · error · com.sun.jna.platform.win32.COM.COMException

ComInterface must define a value for iid

Error message

ComInterface must define a value for iid

What it means

Thrown by ProxyObject's private getIID(ComInterface) helper when the @ComInterface annotation exists but its iid() attribute is null or empty. The IID is mandatory for all proxy operations (QI, advise, unadvise), so an annotation without a GUID is treated as invalid configuration. This is caught during advise/queryInterface flows that do check for the annotation first.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java:519

                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");
        }
    }

    // --------------------- ProxyObject ---------------------

    private String getAccessorName(java.lang.reflect.Method method, ComProperty prop) {
        if (prop.name().isEmpty()) {
            String methName = method.getName();
            if (methName.startsWith("get")) {
                return methName.replaceFirst("get", "");
            } else {
                throw new RuntimeException(
                        "Property Accessor name must start with 'get', or set the anotation 'name' value");
            }
        } else {
            return prop.name();
        }
    }

View on GitHub (pinned to d036ad9781)

Solutions

  1. Set a valid GUID in @ComInterface(iid="{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}")
  2. Validate iid strings with a GUID parser before use in interfaces
  3. Regenerate the annotation value from the COM type library (oleview / tlbimp output)

Example fix

// before
@ComInterface(iid = "")
interface MyEvents extends IComEventCallbackListener { ... }
// after
@ComInterface(iid = "{D666E0F0-...}")
interface MyEvents extends IComEventCallbackListener { ... }
Defensive patterns

Strategy: validation

Validate before calling

ComInterface a = iface.getAnnotation(ComInterface.class); if (a == null || a.iid() == null || a.iid().isEmpty()) throw new IllegalArgumentException("@ComInterface must define non-empty iid on " + iface.getName());

Type guard

boolean hasIid = (Class<?> c) -> c.isAnnotationPresent(ComInterface.class) && !c.getAnnotation(ComInterface.class).iid().isEmpty();

Try / catch

try { proxy.advise(iface, listener); } catch (COMException e) { LOG.error("iid resolution failed", e); }

Prevention

When it happens

Trigger: @ComInterface present with empty iid string, e.g. @ComInterface(iid="") or relying on a default that resolves to empty; annotation processed through a proxy/subclass where iid resolution fails.

Common situations: Copy-pasted annotation where the GUID was deleted; templates with placeholder GUIDs left blank; annotation defined with iid pointing to a constant that failed to initialize.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/7c013c3f5fede302. Report an issue: GitHub.