{"record":{"id":"46d90341744c03d2","repo":"java-native-access/jna","slug":"queryinterface-interface-must-define-a-value-for-iid-via-the","errorCode":null,"errorMessage":"queryInterface: Interface must define a value for iid via the ComInterface annotation","messagePattern":"queryInterface: Interface must define a value for 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/ProxyObject.java","lineNumber":484,"sourceCode":"        if (argParams.length == 0 || !method.isVarArgs() || !(argParams[argParams.length - 1] instanceof Object[])) {\n            return argParams;\n        }\n        // when last parameter is Object[] -> unfold the ellipsis:\n        Object[] varargs = (Object[]) argParams[argParams.length - 1];\n        Object[] args = new Object[argParams.length - 1 + varargs.length];\n        System.arraycopy(argParams, 0, args, 0, argParams.length - 1);\n        System.arraycopy(varargs, 0, args, argParams.length - 1, varargs.length);\n        return args;\n    }\n\n    @Override\n    public <T> T queryInterface(Class<T> comInterface) throws COMException {\n        assert COMUtils.comIsInitialized() : \"COM not initialized\";\n\n        try {\n            ComInterface comInterfaceAnnotation = comInterface.getAnnotation(ComInterface.class);\n            if (null == comInterfaceAnnotation) {\n                throw new COMException(\n                        \"queryInterface: Interface must define a value for iid via the ComInterface annotation\");\n            }\n            final IID iid = this.getIID(comInterfaceAnnotation);\n            final PointerByReference ppvObject = new PointerByReference();\n\n            HRESULT hr = ProxyObject.this.getRawDispatch().QueryInterface(new REFIID(iid), ppvObject);\n\n            if (WinNT.S_OK.equals(hr)) {\n                Dispatch dispatch = new Dispatch(ppvObject.getValue());\n                T t = this.factory.createProxy(comInterface, dispatch);\n                // QueryInterface returns a COM object pointer with a +1\n                // reference, we must drop one,\n                // Note: createProxy adds one;\n                int n = dispatch.Release();\n                return t;\n            } else {\n                String formatMessageFromHR = Kernel32Util.formatMessage(hr);\n                throw new COMException(\"queryInterface: \" + formatMessageFromHR, hr);","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java#L466-L502","documentation":"Thrown by ProxyObject.queryInterface() when the target interface class has no @ComInterface annotation providing an IID. The library needs the IID to build the REFIID for the underlying IDispatch.QueryInterface call. Without it, the request cannot be formulated.","triggerScenarios":"Calling proxy.queryInterface(SomeClass.class) where SomeClass is a plain interface without @ComInterface(iid=\"...\").","commonSituations":"Querying with a helper/utility interface defined ad hoc; forgetting to annotate a new interface added to the codebase; passing java.lang.Cloneable-like generic interfaces by mistake.","solutions":["Add @ComInterface(iid=\"{GUID}\") to the interface being queried","Confirm the GUID matches the COM type library entry","Use the interface returned by Factory.createProxy only with properly annotated interfaces"],"exampleFix":"// before\nFoo foo = proxy.queryInterface(Foo.class); // Foo unannotated\n// after\n@ComInterface(iid=\"{12345678-1234-1234-1234-123456789012}\")\ninterface Foo extends IUnknown { ... }\nFoo foo = proxy.queryInterface(Foo.class);","handlingStrategy":"validation","validationCode":"if (!comInterface.isAnnotationPresent(ComInterface.class)) { throw new IllegalArgumentException(comInterface.getName() + \" needs @ComInterface(iid)\"); }","typeGuard":"boolean isQueryable = (Class<?> c) -> c.isAnnotationPresent(ComInterface.class) && c.getAnnotation(ComInterface.class).iid() != null && !c.getAnnotation(ComInterface.class).iid().isEmpty();","tryCatchPattern":"try { Foo f = proxy.queryInterface(Foo.class); } catch (COMException e) { LOG.error(\"QI failed\", e); }","preventionTips":["Annotate all COM interfaces with valid GUIDs","Validate annotations at startup with reflection","Keep GUIDs in constants shared with type-library regeneration scripts"],"tags":["com","annotation","iid","queryinterface"],"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"}