{"record":{"id":"251482a5773b64e4","repo":"quarkusio/quarkus","slug":"disposer-method-must-not-have-more-than-1-dispose","errorCode":null,"errorMessage":"Disposer method must not have more than 1 @Disposes parameter: ","messagePattern":"Disposer method must not have more than 1 @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":427,"sourceCode":"            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        }\n        if (Annotations.getParameterAnnotations(beanDeployment, disposerMethod)\n                .stream()\n                .filter(it -> DotNames.DISPOSES.equals(it.name()))\n                .count() > 1) {\n            throw new DefinitionException(\"Disposer method must not have more than 1 @Disposes parameter: \"\n                    + disposerMethod);\n        }\n\n        Injection injection = new Injection(disposerMethod,\n                InjectionPointInfo.fromMethod(disposerMethod, beanClass, beanDeployment,\n                        (annotations, position) -> annotations.stream().anyMatch(a -> a.name().equals(DotNames.DISPOSES)),\n                        transformer));\n        injection.injectionPoints.forEach(ipi -> validateInjections(ipi, BeanType.MANAGED_BEAN));\n        return injection;\n    }\n\n    static Injection forObserver(MethodInfo observerMethod, ClassInfo beanClass, BeanDeployment beanDeployment,\n            InjectionPointModifier transformer) {\n        return new Injection(observerMethod, InjectionPointInfo.fromMethod(observerMethod, beanClass, beanDeployment,\n                (annotations, position) -> annotations.stream()\n                        .anyMatch(a -> a.name().equals(DotNames.OBSERVES) || a.name().equals(DotNames.OBSERVES_ASYNC)),\n                transformer));\n    }","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java#L409-L445","documentation":"A CDI definition error thrown by the ArC processor while building injection metadata for a disposer method (Injection.forDisposer). A disposer method identifies the bean instance it cleans up via exactly one @Disposes parameter; this guard counts @Disposes-annotated parameters and fires when more than one is present, because the container cannot decide which parameter represents the disposed producer. The method itself is not otherwise invalid - only the duplicated @Disposes annotation is at fault.","triggerScenarios":"Declaring two or more parameters annotated @Disposes on a single disposer method; detected in Injection.forDisposer.","commonSituations":"Trying to dispose two beans in one method; copy-paste duplication of the @Disposes annotation across parameters.","solutions":["Keep exactly one @Disposes parameter; remove @Disposes from the extra parameters (they become regular injection points)","Split disposal logic into separate disposer methods, one per bean type"],"exampleFix":"// before\nvoid dispose(@Disposes Widget a, @Disposes Gadget b) {}\n// after\nvoid dispose(@Disposes Widget a, Gadget b) {}","handlingStrategy":"validation","validationCode":"for (Method m : MyClass.class.getDeclaredMethods()) {\n    long count = java.util.Arrays.stream(m.getParameterAnnotations()).flatMap(java.util.Arrays::stream)\n        .filter(a -> a.annotationType().getSimpleName().equals(\"Disposes\")).count();\n    if (count > 1) throw new IllegalStateException(\"Multiple @Disposes params: \" + m);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Exactly one @Disposes parameter per disposer method","Other parameters of a disposer are plain injection points — do not annotate them @Disposes"],"tags":["cdi","arc","disposer"],"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-12T22:17:10.623Z"}