{"record":{"id":"6f683d20d0b394ce","repo":"quarkusio/quarkus","slug":"multiple-disposer-methods-found-for-producer-pr","errorCode":null,"errorMessage":"Multiple disposer methods found for producer '${producer}' declared on ${declaringBean}:\n\t- ${disposerMethod}","messagePattern":"Multiple disposer methods found for producer '(.+?)' declared on (.+?):\n\t- (.+?)","errorType":"exception","errorClass":"DefinitionException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java","lineNumber":1558,"sourceCode":"                }\n                if (hasQualifier) {\n                    Type disposedParamType = disposer.getDisposedParameterType();\n                    for (Type beanType : beanTypes) {\n                        if (beanResolver.matches(disposedParamType, beanType)) {\n                            found.add(disposer);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        if (found.size() > 1) {\n            StringBuilder error = new StringBuilder(\"Multiple disposer methods found for producer '\")\n                    .append(producer).append(\"' declared on \").append(declaringBean).append(\":\\n\");\n            for (DisposerInfo disposer : found) {\n                error.append(\"\\t- \").append(disposer.getDisposerMethod()).append(\"\\n\");\n            }\n            throw new DefinitionException(error.toString());\n        }\n        return found.isEmpty() ? null : found.get(0);\n    }\n\n    // keep it public we need this method in quarkus integration\n    public static Set<DotName> initBeanDefiningAnnotations(Collection<BeanDefiningAnnotation> additionalBeanDefiningAnnotations,\n            Set<DotName> stereotypes) {\n        Set<DotName> beanDefiningAnnotations = new HashSet<>();\n        for (BuiltinScope scope : BuiltinScope.values()) {\n            beanDefiningAnnotations.add(scope.getInfo().getDotName());\n        }\n        if (additionalBeanDefiningAnnotations != null) {\n            for (BeanDefiningAnnotation additional : additionalBeanDefiningAnnotations) {\n                beanDefiningAnnotations.add(additional.getAnnotation());\n            }\n        }\n        beanDefiningAnnotations.addAll(stereotypes);\n        return beanDefiningAnnotations;","sourceCodeStart":1540,"sourceCodeEnd":1576,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java#L1540-L1576","documentation":"CDI allows at most one disposer method per producer. If two or more disposer methods resolve to the same producer (matching the produced type and qualifiers) within the same bean class, ArC throws this DefinitionException listing all offending disposer methods.","triggerScenarios":"Two @Disposes methods in a bean class both accept parameters assignable to the same producer's type/qualifiers — typically duplicates created by inheritance or copy-paste of a close()/cleanup() method.","commonSituations":"Copy-pasting a disposer to handle cleanup differently; subclass adding a disposer for an inherited producer; merging branches that each added a disposer for the same producer.","solutions":["Delete one of the duplicate disposer methods, consolidating cleanup logic into the remaining one.","If both cleanups are needed, call both operations from a single disposer method.","Rename qualifiers/types so each disposer matches a distinct producer."],"exampleFix":"// before\nclass Cfg {\n  @Produces Conn connect() { ... }\n  @Disposes void closeA(Conn c) { c.close(); }\n  @Disposes void closeB(Conn c) { c.release(); }\n}\n// after\nclass Cfg {\n  @Produces Conn connect() { ... }\n  @Disposes void close(Conn c) { c.release(); c.close(); }\n}","handlingStrategy":"validation","validationCode":"// At build time: count disposer methods per bean class\nlong disposers = Arrays.stream(cls.getDeclaredMethods())\n        .filter(m -> Arrays.stream(m.getParameterAnnotations())\n                .flatMap(Stream::of).anyMatch(a -> a instanceof Disposes.class)).count();\nif (disposers > 1) {\n    throw new IllegalStateException(\"More than one disposer in \" + cls);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["One disposer per bean class; consolidate cleanup there","Refactor multi-step cleanup into a single disposer body","Watch for inherited producers plus subclass disposers"],"tags":["cdi","quarkus-arc","disposer","ambiguous"],"backgroundTag":"duplicate-disposer-method","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"}