{"record":{"id":"ec241f244c77e3ee","repo":"quarkusio/quarkus","slug":"disposer-method-must-not-be-annotated-inject-alt","errorCode":null,"errorMessage":"Disposer method must not be annotated @Inject (alternatively, initializer method must not have a @Disposes parameter): ","messagePattern":"Disposer method must not be annotated @Inject \\(alternatively, initializer method must not have a @Disposes parameter\\): ","errorType":"validation","errorClass":"DefinitionException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java","lineNumber":404,"sourceCode":"        if (!classInfo.superName().equals(DotNames.OBJECT)) {\n            ClassInfo info = getClassByName(beanDeployment.getBeanArchiveIndex(), classInfo.superName());\n            if (info != null) {\n                List<Injection> superInjections = forClassBean(beanClass, info, beanDeployment, transformer, true, seenMethods);\n\n                // injections are discovered bottom-up to easily skip overriden methods,\n                // but they need to be performed top-down per the AtInject specification\n                superInjections.addAll(injections);\n                injections = superInjections;\n            }\n        }\n\n        return injections;\n    }\n\n    static Injection forDisposer(MethodInfo disposerMethod, ClassInfo beanClass, BeanDeployment beanDeployment,\n            InjectionPointModifier transformer) {\n        if (beanDeployment.hasAnnotation(disposerMethod, DotNames.INJECT)) {\n            throw new DefinitionException(\"Disposer method must not be annotated @Inject \"\n                    + \"(alternatively, initializer method must not have a @Disposes parameter): \"\n                    + disposerMethod);\n        }\n        if (beanDeployment.hasAnnotation(disposerMethod, DotNames.PRODUCES)) {\n            throw new DefinitionException(\"Disposer method must not be annotated @Produces \"\n                    + \"(alternatively, producer method must not have a @Disposes parameter): \"\n                    + disposerMethod);\n        }\n        if (Annotations.hasParameterAnnotation(beanDeployment, disposerMethod, DotNames.OBSERVES)) {\n            throw new DefinitionException(\"Disposer method must not have an @Observes parameter \"\n                    + \"(alternatively, observer method must not have a @Disposes parameter): \"\n                    + disposerMethod);\n        }\n        if (Annotations.hasParameterAnnotation(beanDeployment, disposerMethod, DotNames.OBSERVES_ASYNC)) {\n            throw new DefinitionException(\"Disposer method must not have an @ObservesAsync parameter \"\n                    + \"(alternatively, async observer method must not have a @Disposes parameter): \"\n                    + disposerMethod);\n        }","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java#L386-L422","documentation":"Build-time CDI definition error from Injection.forDisposer: the method recognized as a disposer (it has a @Disposes parameter) is itself annotated @Inject, i.e. the same method is both an initializer and a disposer. The CDI spec forbids this combination; the offending method is appended to the message.","triggerScenarios":"Annotating a @Disposes-parameter method with @Inject; detected in Injection.forDisposer at build time.","commonSituations":"Adding @Inject to a disposer thinking it enables injection into its other parameters; combining producer/disposer/injector roles on one method after refactoring.","solutions":["Remove @Inject from the disposer method; its non-@Disposes parameters are resolved as injection points automatically","Move initialization logic into a separate @Inject initializer method","Drop the @Disposes parameter if the method was meant to be a plain initializer"],"exampleFix":"// before\n@Inject\nvoid dispose(@Disposes Widget w) {}\n// after\nvoid dispose(@Disposes Widget w) {}","handlingStrategy":"validation","validationCode":"for (Method m : MyClass.class.getDeclaredMethods()) {\n    boolean hasDisposes = java.util.Arrays.stream(m.getParameterAnnotations())\n        .flatMap(java.util.Arrays::stream).anyMatch(a -> a.annotationType().getSimpleName().equals(\"Disposes\"));\n    if (hasDisposes && m.isAnnotationPresent(Inject.class)) {\n        throw new IllegalStateException(\"@Inject disposer: \" + m);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never combine @Inject with a @Disposes parameter","Give each lifecycle role (inject/produce/dispose/observe) its own method"],"tags":["cdi","arc","disposer","inject"],"backgroundTag":"disposer-method-role-conflict","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}