{"record":{"id":"c75da7d8d05f815e","repo":"quarkusio/quarkus","slug":"consumeevent-annotation-must-target-a-method","errorCode":null,"errorMessage":"@ConsumeEvent annotation must target a method","messagePattern":"@ConsumeEvent annotation must target a method","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/vertx/deployment/src/main/java/io/quarkus/vertx/deployment/EventBusCodecProcessor.java","lineNumber":64,"sourceCode":"    private static final DotName LOCAL_EVENT_BUT_CODEC = DotName.createSimple(LocalEventBusCodec.class);\n\n    @BuildStep\n    public void registerCodecs(\n            BeanArchiveIndexBuildItem beanArchiveIndexBuildItem,\n            CombinedIndexBuildItem combinedIndex,\n            BuildProducer<MessageCodecBuildItem> messageCodecs,\n            BuildProducer<ReflectiveClassBuildItem> reflectiveClass,\n            BuildProducer<LocalCodecSelectorTypesBuildItem> localCodecSelectorTypes) {\n\n        final IndexView index = beanArchiveIndexBuildItem.getIndex();\n        Collection<AnnotationInstance> consumeEventAnnotationInstances = index.getAnnotations(CONSUME_EVENT);\n        Map<DotName, DotName> codecByTypes = new HashMap<>();\n        Set<DotName> selectorTypes = new HashSet<>();\n\n        for (AnnotationInstance consumeEventAnnotationInstance : consumeEventAnnotationInstances) {\n            AnnotationTarget typeTarget = consumeEventAnnotationInstance.target();\n            if (typeTarget.kind() != AnnotationTarget.Kind.METHOD) {\n                throw new IllegalStateException(\"@ConsumeEvent annotation must target a method\");\n            }\n            MethodInfo method = typeTarget.asMethod();\n\n            Type codecTargetFromParameter = extractPayloadTypeFromParameter(method);\n            // If the @ConsumeEvent set the codec, use this codec. It applies to the parameter\n            AnnotationValue codec = consumeEventAnnotationInstance.value(\"codec\");\n            if (codec != null && codec.asClass().kind() == Type.Kind.CLASS) {\n                if (codecTargetFromParameter == null) {\n                    throw new IllegalStateException(\"Invalid `codec` argument in @ConsumeEvent - no parameter\");\n                }\n                codecByTypes.put(codecTargetFromParameter.name(), codec.asClass().asClassType().name());\n            } else if (codecTargetFromParameter != null && !hasBuiltInCodec(codecTargetFromParameter)) {\n                // Codec is not set and built-in codecs cannot be used\n                if (!codecByTypes.containsKey(codecTargetFromParameter.name())) {\n                    if (isConcreteClass(codecTargetFromParameter, index)) {\n                        // The default codec makes only sense for concrete classes\n                        LOGGER.debugf(\"Local Message Codec registered for type %s\",\n                                codecTargetFromParameter);","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/vertx/deployment/src/main/java/io/quarkus/vertx/deployment/EventBusCodecProcessor.java#L46-L82","documentation":"During build, EventBusCodecProcessor scans @ConsumeEvent annotations to register custom codecs and expects each annotation to be on a method (the event consumer). If an instance targets something else (e.g. a class or field), the build fails with this IllegalStateException.","triggerScenarios":"Putting @ConsumeEvent on a class, field, or constructor instead of a business method; annotation-placement mistakes or copy/paste from other messaging annotations.","commonSituations":"Developer annotates a bean class thinking it registers a consumer; IDE auto-import places the annotation on the wrong element; migration from another framework's annotation semantics.","solutions":["Move @ConsumeEvent onto a public method that takes the event payload parameter","Remove the annotation from the class/field","If you intended class-level subscription, implement an observer bean method instead"],"exampleFix":"// before\n@ConsumeEvent\n@ApplicationScoped\npublic class MyConsumer { }\n// after\n@ApplicationScoped\npublic class MyConsumer {\n    @ConsumeEvent(\"my-address\")\n    public void consume(String msg) { }\n}","handlingStrategy":"validation","validationCode":"// check placement before build\nfor (var f : MyConsumer.class.getDeclaredMethods()) {\n    if (f.isAnnotationPresent(ConsumeEvent.class) && f.getParameterCount() == 0)\n        throw new IllegalStateException(\"@ConsumeEvent must be on a method with a payload parameter\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only annotate consumer methods with @ConsumeEvent","Run a compile/build early to catch build-time validation","Don't mix class-level and method-level messaging annotations"],"tags":["quarkus","vertx","event-bus","annotation-misuse","build-time"],"backgroundTag":"invalid-annotation-target","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}