{"record":{"id":"453b8cc39480beac","repo":"quarkusio/quarkus","slug":"disposer-method-must-not-have-an-observesasync-pa","errorCode":null,"errorMessage":"Disposer method must not have an @ObservesAsync parameter (alternatively, async observer method must not have a @Disposes parameter): ","messagePattern":"Disposer method must not have an @ObservesAsync parameter \\(alternatively, async observer 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":419,"sourceCode":"    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        }\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    }","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java#L401-L437","documentation":"Build-time CDI definition error from Injection.forDisposer: the method declares more than one parameter annotated @Disposes. Exactly one disposed parameter is allowed per disposer method; the method signature follows the message.","triggerScenarios":"Declaring a method with both a @Disposes parameter and an @ObservesAsync parameter; detected in Injection.forDisposer.","commonSituations":"Combining async event handling with disposal in one method; refactoring observers into disposers or vice versa.","solutions":["Split into two methods: one @ObservesAsync observer, one disposer with @Disposes","Remove the @ObservesAsync parameter from the disposer","Remove the @Disposes parameter if the method was meant to be an async observer"],"exampleFix":"// before\nvoid both(@ObservesAsync Ev e, @Disposes Widget w) {}\n// after\nvoid observe(@ObservesAsync Ev e) {}\nvoid dispose(@Disposes Widget w) {}","handlingStrategy":"validation","validationCode":"for (Method m : MyClass.class.getDeclaredMethods()) {\n    var names = java.util.Arrays.stream(m.getParameterAnnotations()).flatMap(java.util.Arrays::stream)\n        .map(a -> a.annotationType().getSimpleName()).collect(java.util.stream.Collectors.toSet());\n    if (names.contains(\"Disposes\") && names.contains(\"ObservesAsync\")) throw new IllegalStateException(\"Async observer+disposer: \" + m);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep @ObservesAsync handlers free of @Disposes parameters","Split async event consumption and disposal into separate methods"],"tags":["cdi","arc","disposer","observer","async"],"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"}