{"record":{"id":"f90741c905d4a8d5","repo":"quarkusio/quarkus","slug":"type-of-injected-decorator-t-does-not-match-the-t","errorCode":null,"errorMessage":"Type of injected Decorator<T> does not match the type of the bean declaring the injection point. Problematic injection point: ${injectionPointInfo.getTargetInfo()}","messagePattern":"Type of injected Decorator<T> does not match the type of the bean declaring the injection point\\. Problematic injection point: (.+?)","errorType":"exception","errorClass":"DefinitionException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java","lineNumber":190,"sourceCode":"        if (beanType == BeanType.DECORATOR) {\n            // the injection point is a field, an initializer method parameter or a bean constructor, with qualifier\n            // @Default, then the type parameter of the injected Decorator must be the same as the type\n            // declaring the injection point\n            if (injectionPointInfo.getRequiredType().name().equals(DotNames.DECORATOR)\n                    && injectionPointInfo.getRequiredType().kind() == Type.Kind.PARAMETERIZED_TYPE\n                    && injectionPointInfo.getRequiredType().asParameterizedType().arguments().size() == 1) {\n                Type actualType = injectionPointInfo.getRequiredType().asParameterizedType().arguments().get(0);\n                AnnotationTarget ipTarget = injectionPointInfo.getAnnotationTarget();\n                DotName expectedType = null;\n                if (ipTarget.kind() == Kind.FIELD) {\n                    expectedType = ipTarget.asField().declaringClass().name();\n                } else if (ipTarget.kind() == Kind.METHOD_PARAMETER) {\n                    expectedType = ipTarget.asMethodParameter().method().declaringClass().name();\n                }\n                if (expectedType != null\n                        // This is very rudimentary check, might need to be expanded?\n                        && !expectedType.equals(actualType.name())) {\n                    throw new DefinitionException(\n                            \"Type of injected Decorator<T> does not match the type of the bean declaring the \" +\n                                    \"injection point. Problematic injection point: \" + injectionPointInfo.getTargetInfo());\n                }\n            }\n\n            // the injection point is a field, an initializer method parameter or a bean constructor of a decorator,\n            // with qualifier @Decorated, then the type parameter of the injected Bean must be the same as the delegate type\n            //\n            // a validation for the specification text above would naturally belong here, but we don't have\n            // access to the delegate type yet, so this is postponed to `Beans.validateInterceptorDecorator()`\n        }\n    }\n\n    private static void validateInjections(List<Injection> injections, BeanType beanType) {\n        for (Injection injection : injections) {\n            for (InjectionPointInfo ipi : injection.injectionPoints) {\n                validateInjections(ipi, beanType);\n            }","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java#L172-L208","documentation":"When Decorator<T> is injected with qualifier @Default, the CDI spec requires T to match the type of the bean declaring the injection point (the decorator itself). ArC compares the declaring class with T and throws this DefinitionException when they differ.","triggerScenarios":"Injecting Decorator<SomeOtherType> into a decorator whose own type differs, e.g. class MyDecorator { @Inject Decorator<Other> other; }.","commonSituations":"Copying interceptor metadata snippets into decorators; using a supertype instead of the decorator's own type.","solutions":["Change the type parameter to the exact type of the decorator declaring the injection point","Use Decorator<?> with unbound wildcard if typed form is not required","Remove the injection point if unused"],"exampleFix":"// before\n@Decorator class MyDecorator { @Inject Decorator<Other> meta; }\n// after\n@Decorator class MyDecorator { @Inject Decorator<MyDecorator> meta; }","handlingStrategy":"validation","validationCode":"Field f = MyDecorator.class.getDeclaredField(\"meta\");\nif (f.getGenericType().getTypeName().contains(\"Decorator<\") && !f.getGenericType().getTypeName().endsWith(\"<MyDecorator>\"))\n    throw new IllegalStateException(\"Decorator<T> must match the declaring decorator type\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Type parameter of Decorator<T> must equal the decorator's own class","Avoid copying interceptor metadata patterns into decorators verbatim","Rely on build-time ArC validation by building after edits"],"tags":["cdi","arc","decorator","bean-metadata","generics","build-time"],"backgroundTag":"cdi-bean-metadata-type-mismatch","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"}