{"record":{"id":"644c6c26a8d2f74c","repo":"quarkusio/quarkus","slug":"bean-constructor-must-not-have-an-observes-parame","errorCode":null,"errorMessage":"Bean constructor must not have an @Observes parameter: ","messagePattern":"Bean constructor must not have an @Observes parameter: ","errorType":"validation","errorClass":"DefinitionException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java","lineNumber":234,"sourceCode":"                    transformer, false, new HashSet<>());\n\n            Set<AnnotationTarget> injectConstructors = injections.stream().filter(Injection::isConstructor)\n                    .map(Injection::getTarget).collect(Collectors.toSet());\n            if (injectConstructors.size() > 1) {\n                throw new DefinitionException(\n                        \"Multiple @Inject constructors found on \" + beanTarget.asClass().name() + \":\\n\"\n                                + injectConstructors.stream().map(Object::toString).collect(Collectors.joining(\"\\n\")));\n            }\n            for (AnnotationTarget injectConstructor : injectConstructors) {\n                Set<AnnotationInstance> parameterAnnotations = Annotations.getParameterAnnotations(beanDeployment,\n                        injectConstructor.asMethod());\n                for (AnnotationInstance annotation : parameterAnnotations) {\n                    if (DotNames.DISPOSES.equals(annotation.name())) {\n                        throw new DefinitionException(\n                                \"Bean constructor must not have a @Disposes parameter: \" + injectConstructor);\n                    }\n                    if (DotNames.OBSERVES.equals(annotation.name())) {\n                        throw new DefinitionException(\n                                \"Bean constructor must not have an @Observes parameter: \" + injectConstructor);\n                    }\n                    if (DotNames.OBSERVES_ASYNC.equals(annotation.name())) {\n                        throw new DefinitionException(\n                                \"Bean constructor must not have an @ObservesAsync parameter: \" + injectConstructor);\n                    }\n                }\n            }\n\n            Set<MethodInfo> initializerMethods = injections.stream()\n                    .filter(it -> it.isMethod() && !it.isConstructor())\n                    .map(Injection::getTarget)\n                    .map(AnnotationTarget::asMethod)\n                    .collect(Collectors.toSet());\n            for (MethodInfo initializerMethod : initializerMethods) {\n                if (beanDeployment.hasAnnotation(initializerMethod, DotNames.PRODUCES)) {\n                    throw new DefinitionException(\"Initializer method must not be annotated @Produces \"\n                            + \"(alternatively, producer method must not be annotated @Inject): \"","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java#L216-L252","documentation":"ArC throws this DefinitionException at build time when a bean constructor declares a parameter annotated with @Observes. Observer method parameters belong only on @Observes methods; constructors may only declare injection points. The CDI spec forbids observer annotations on bean constructors, and Injection.forBean enforces this while scanning the constructor's parameter annotations.","triggerScenarios":"Annotating a parameter of a bean's @Inject constructor with @jakarta.enterprise.event.Observes (or @Observes(priority)), so ArC detects DotNames.OBSERVES on the constructor while processing inject constructors in forBean.","commonSituations":"Developer intends the bean to receive events and mistakenly puts @Observes on the constructor parameter; refactoring an observer method into a constructor; auto-generated constructor stubs that kept an @Observes parameter.","solutions":["Remove @Observes from the constructor parameter","Add a dedicated observer method: void onEvent(@Observes MyEvent e) { ... } inside the bean","Inject the event payload type as a normal injection point if you actually need it in the constructor","Rebuild; the exception is raised during Quarkus augmentation, not at runtime"],"exampleFix":"// before\n@Inject\nMyBean(@Observes StartupEvent e) { ... }\n\n// after\n@Inject\nMyBean() { }\n\nvoid onStart(@Observes StartupEvent e) { ... }","handlingStrategy":"validation","validationCode":"void checkConstructor(Method ctor) throws Exception {\n    for (var p : ctor.getParameters()) {\n        if (p.isAnnotationPresent(jakarta.enterprise.event.Observes.class)) {\n            throw new IllegalStateException(\"@Observes on constructor param: \" + ctor);\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Put @Observes only on void observer methods with one event parameter","Handle StartupEvent via a dedicated method, never the constructor","Keep bean constructors limited to plain injection parameters","Review refactors that move observer code — event annotations must move to methods, not constructors"],"tags":["cdi","arc","observes","bean-definition","build-time"],"backgroundTag":"cdi-bean-definition-invalid","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"}