{"record":{"id":"8f09bd3377bf8667","repo":"java-native-access/jna","slug":"cominterface-must-define-a-value-for-iid","errorCode":null,"errorMessage":"ComInterface must define a value for iid","messagePattern":"ComInterface must define a value for iid","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":97,"sourceCode":"        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();\n                if (-1 == dispId) {\n                    dispId = this.fetchDispIdFromName(callbackAnnotation);\n                }\n                if (dispId == -1) {\n                    CallbackProxy.this.comEventCallbackListener.errorReceivingCallbackEvent(","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java#L79-L115","documentation":"This variant fires when the @ComInterface annotation IS present but its iid() attribute is null or empty. createRIID needs a valid GUID string to build the REFIID used for COM event advising. A present-but-empty iid is a configuration mistake inside the annotation itself.","triggerScenarios":"Declaring @ComInterface without the iid attribute (or with iid = \"\") on an interface used as a COM event callback; building the annotation dynamically and leaving iid unset.","commonSituations":"Copying an @ComInterface declaration from another interface and forgetting to fill in the new GUID; using a placeholder that was never replaced; annotation defined with only the value attribute while code reads iid().","solutions":["Set @ComInterface(iid=\"{valid-guid}\") with the real IID from the type library","Look the IID up with a tool such as OLE/COM Object Viewer or the .tlb contents","Validate the GUID string format before runtime (new IID(iidStr) will also fail on malformed GUIDs)"],"exampleFix":"// before\n@ComInterface\npublic interface IApplicationEvents extends IComEventCallbackListener { ... }\n// after\n@ComInterface(iid = \"{61A762AF-3C1E-4B0C-9A1F-5E1F0E14C9F2}\")\npublic interface IApplicationEvents extends IComEventCallbackListener { ... }","handlingStrategy":"validation","validationCode":"ComInterface a = iface.getAnnotation(ComInterface.class);\nif (a == null || a.iid() == null || a.iid().isEmpty())\n    throw new IllegalArgumentException(iface.getName() + \" must set @ComInterface(iid=...)\");","typeGuard":null,"tryCatchPattern":"try { factory.addEventListener(iface, method, listener); } catch (COMException e) { if (e.getMessage().contains(\"value for iid\")) { /* supply iid */ } }","preventionTips":["Never declare @ComInterface without iid","Copy GUIDs from the type library, not placeholders","Add a startup check that all event interfaces define non-empty iids"],"tags":["java","com","annotation","guid","iid"],"backgroundTag":"empty-required-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"}