{"record":{"id":"b11ccd99dbdfab03","repo":"java-native-access/jna","slug":"advise-interface-must-define-a-value-for-either-iid-via-the","errorCode":null,"errorMessage":"advise: Interface must define a value for either iid via the ComInterface annotation","messagePattern":"advise: Interface must define a value for either iid via the ComInterface annotation","errorType":"exception","errorClass":"com.sun.jna.platform.win32.COM.COMException","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java","lineNumber":92,"sourceCode":"        this.factory = factory;\n        this.comEventCallbackInterface = comEventCallbackInterface;\n        this.comEventCallbackListener = comEventCallbackListener;\n        this.listenedToRiid = this.createRIID(comEventCallbackInterface);\n        this.dsipIdMap = this.createDispIdMap(comEventCallbackInterface);\n        this.dispatchListener = new DispatchListener(this);\n    }\n\n    ObjectFactory factory;\n    Class<?> comEventCallbackInterface;\n    IComEventCallbackListener comEventCallbackListener;\n    REFIID listenedToRiid;\n    public DispatchListener dispatchListener;\n    Map<DISPID, Method> dsipIdMap;\n\n    private REFIID createRIID(Class<?> comEventCallbackInterface) {\n        ComInterface comInterfaceAnnotation = comEventCallbackInterface.getAnnotation(ComInterface.class);\n        if (null == comInterfaceAnnotation) {\n            throw new COMException(\n                    \"advise: Interface must define a value for either iid via the ComInterface annotation\");\n        }\n        String iidStr = comInterfaceAnnotation.iid();\n        if (null == iidStr || iidStr.isEmpty()) {\n            throw new COMException(\"ComInterface must define a value for iid\");\n        }\n        return new REFIID(new IID(iidStr).getPointer());\n    }\n\n    @SuppressWarnings(\"deprecation\") // ComEventCallback is used here to be backwards compatible\n    private Map<DISPID, Method> createDispIdMap(Class<?> comEventCallbackInterface) {\n        Map<DISPID, Method> map = new HashMap<>();\n\n        for (Method meth : comEventCallbackInterface.getMethods()) {\n            ComEventCallback callbackAnnotation = meth.getAnnotation(ComEventCallback.class);\n            ComMethod methodAnnotation = meth.getAnnotation(ComMethod.class);\n            if (methodAnnotation != null) {\n                int dispId = methodAnnotation.dispId();","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java#L74-L110","documentation":"CallbackProxy.createRIID resolves the IID of a COM event callback interface by reading its @ComInterface annotation; if the annotation is absent it throws this COMException. The proxy needs the interface's GUID (IID) to Advise/Unadvise event sinks and cannot proceed without it.","triggerScenarios":"Passing a callback interface (annotated only with @ComEventCallback or none at all, not @ComInterface) to ObjectFactory.addEventListener / CallbackProxy construction; renaming or deleting the @ComInterface annotation during refactoring.","commonSituations":"Hand-writing a COM event interface and forgetting the annotation; moving an interface between packages so an annotation import is lost; migrating from the deprecated ComEventCallback style to the annotation-based util API.","solutions":["Annotate the event callback interface with @ComInterface(iid=\"{GUID}\")","Ensure the correct guid attribute (iid) is present, matching the type library","Rebuild so the annotation is actually compiled onto the interface passed to advise","If the interface already has @ComObject (for createObject), note advise needs @ComInterface instead"],"exampleFix":"// before\npublic interface IDocumentEvents extends IComEventCallbackListener { ... }\n// after\n@ComInterface(iid = \"{A3B2C1D0-1234-5678-9ABC-DEF012345678}\")\npublic interface IDocumentEvents extends IComEventCallbackListener { ... }","handlingStrategy":"validation","validationCode":"if (iface.getAnnotation(ComInterface.class) == null)\n    throw new IllegalArgumentException(iface.getName() + \" needs @ComInterface before advising events\");","typeGuard":null,"tryCatchPattern":"try { factory.addEventListener(iface, method, listener); } catch (COMException e) { if (e.getMessage().contains(\"ComInterface annotation\")) { /* fix annotation */ } }","preventionTips":["Always pair event callback interfaces with @ComInterface(iid=...)","Check annotations when migrating event interfaces between APIs","Unit-test interface setup before touching live COM"],"tags":["java","com","annotation","events","iid"],"backgroundTag":"missing-required-config-field","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}