{"record":{"id":"a3d97a97f01435c9","repo":"quarkusio/quarkus","slug":"decorator-declares-a-disposer-method-decoratorc","errorCode":null,"errorMessage":"Decorator declares a disposer method: ${decoratorClass}","messagePattern":"Decorator declares a disposer method: (.+?)","errorType":"exception","errorClass":"DefinitionException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Decorators.java","lineNumber":168,"sourceCode":"            }\n        }\n\n        checkDecoratorFieldsAndMethods(decoratorClass, beanDeployment);\n\n        return new DecoratorInfo(decoratorClass, beanDeployment, delegateInjectionPoint,\n                decoratedTypes, injections, priority);\n    }\n\n    private static void checkDecoratorFieldsAndMethods(ClassInfo decoratorClass, BeanDeployment beanDeployment) {\n        ClassInfo aClass = decoratorClass;\n        while (aClass != null) {\n            for (MethodInfo method : aClass.methods()) {\n                if (beanDeployment.hasAnnotation(method, DotNames.PRODUCES)) {\n                    throw new DefinitionException(\"Decorator declares a producer method: \" + decoratorClass);\n                }\n                // the following 3 checks rely on the annotation store returning parameter annotations for methods\n                if (beanDeployment.hasAnnotation(method, DotNames.DISPOSES)) {\n                    throw new DefinitionException(\"Decorator declares a disposer method: \" + decoratorClass);\n                }\n                if (beanDeployment.hasAnnotation(method, DotNames.OBSERVES)) {\n                    throw new DefinitionException(\"Decorator declares an observer method: \" + decoratorClass);\n                }\n                if (beanDeployment.hasAnnotation(method, DotNames.OBSERVES_ASYNC)) {\n                    throw new DefinitionException(\"Decorator declares an async observer method: \" + decoratorClass);\n                }\n            }\n\n            for (FieldInfo field : aClass.fields()) {\n                if (beanDeployment.hasAnnotation(field, DotNames.PRODUCES)) {\n                    throw new DefinitionException(\"Decorator declares a producer field: \" + decoratorClass);\n                }\n            }\n\n            DotName superClass = aClass.superName();\n            aClass = superClass != null && !superClass.equals(DotNames.OBJECT)\n                    ? getClassByName(beanDeployment.getBeanArchiveIndex(), superClass)","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Decorators.java#L150-L186","documentation":"Build-time CDI definition error: while walking the decorator's class hierarchy, ArC found a method with a @Disposes parameter. Disposer methods belong to producer classes, not decorators; the decorator class in the message declares one and deployment fails.","triggerScenarios":"A @Decorator class contains a method with a @Disposes-annotated parameter, found during createDecorator via checkDecoratorFieldsAndMethods.","commonSituations":"Merging disposer logic from a producer bean into a decorator; leftover disposer after converting a class into a decorator; copying a disposer method into the decorator for convenience.","solutions":["Remove the @Disposes parameter/method from the decorator.","Move disposal to the bean that declares the corresponding @Produces method.","Split responsibilities: keep the decorator only for interception logic.","Audit superclasses, since the check walks the whole hierarchy."],"exampleFix":"// before\n@Decorator\npublic class D implements Greeter {\n    void dispose(@Disposes Resource r) { r.close(); }\n}\n\n// after\n@Decorator\npublic class D implements Greeter { /* no disposer */ }","handlingStrategy":"validation","validationCode":"if (decoratorClass.getAnnotation(jakarta.decorator.Decorator.class) != null)\n    for (Method m : decoratorClass.getMethods())\n        if (Arrays.stream(m.getParameters()).anyMatch(p -> p.isAnnotationPresent(jakarta.enterprise.inject.Disposes.class)))\n            throw new IllegalStateException(\"Decorator cannot declare disposer: \" + m);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep disposal in the bean that produces the object, never in a decorator.","Add an automated rule banning @Disposes inside @Decorator classes."],"tags":["cdi","decorator","disposer","illegal-annotation"],"backgroundTag":"illegal-annotation-on-decorator","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}