{"record":{"id":"45dbcedaae6e8046","repo":"quarkusio/quarkus","slug":"injected-intercepted-bean-has-to-use-unbound-w","errorCode":null,"errorMessage":"Injected @Intercepted Bean<?> has to use unbound wildcard as its type parameter. Problematic injection point: ${injectionPointInfo.getTargetInfo()}","messagePattern":"Injected @Intercepted Bean<\\?> has to use unbound wildcard as its type parameter\\. 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":144,"sourceCode":"                    throw new DefinitionException(\n                            \"Type of injected Bean<T> does not match the type of the bean declaring the \" +\n                                    \"injection point. Problematic injection point: \" + injectionPointInfo.getTargetInfo());\n                }\n            }\n        }\n        if (beanType == BeanType.INTERCEPTOR) {\n            // the injection point is a field, an initializer method parameter or a bean constructor of an interceptor,\n            // with qualifier @Intercepted, then the type parameter of the injected Bean must be an unbounded wildcard\n            if (injectionPointInfo.getRequiredType().name().equals(DotNames.BEAN)\n                    && injectionPointInfo.getRequiredQualifier(DotNames.INTERCEPTED) != null\n                    && injectionPointInfo.getRequiredType().kind() == Type.Kind.PARAMETERIZED_TYPE) {\n                ParameterizedType parameterizedType = injectionPointInfo.getRequiredType().asParameterizedType();\n                // there should be exactly one param - wildcard - and it has to be unbound; all else is DefinitionException\n                if (parameterizedType.arguments().size() != 1\n                        || !(parameterizedType.arguments().get(0).kind() == Type.Kind.WILDCARD_TYPE)\n                        || !(parameterizedType.arguments().get(0).asWildcardType().extendsBound().name().equals(DotNames.OBJECT)\n                                && parameterizedType.arguments().get(0).asWildcardType().superBound() == null)) {\n                    throw new DefinitionException(\n                            \"Injected @Intercepted Bean<?> has to use unbound wildcard as its type parameter. \" +\n                                    \"Problematic injection point: \" + injectionPointInfo.getTargetInfo());\n                }\n            }\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 Bean, or Interceptor must be the same as the type\n            // declaring the injection point\n            if (injectionPointInfo.getRequiredType().name().equals(DotNames.INTERCEPTOR_BEAN)\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                }","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java#L126-L162","documentation":"When Bean<T> is injected with the @Intercepted qualifier, the CDI spec mandates the type parameter be an unbound wildcard (Bean<?>). ArC validates the required type is a parameterized type with exactly one argument — a wildcard with no super bound and java.lang.Object extends bound — and throws this DefinitionException otherwise.","triggerScenarios":"Injecting @Intercepted with a concrete type parameter (Bean<MyBean>), a bounded wildcard (Bean<? extends X>), a super-bound wildcard (Bean<? super X>), or a non-parameterized raw Bean type.","commonSituations":"IDE auto-completing a concrete type parameter; misunderstanding that @Intercepted metadata is typed; mixing up rules for plain Bean<T> vs @Intercepted Bean<?> injections.","solutions":["Change the injection point to use the unbound wildcard: @Inject @Intercepted Bean<?> bean","Remove the @Intercepted qualifier if a typed Bean<T> was intended and legal in that context","Move the injection into an interceptor class (also required — see the @Intercepted placement rule)"],"exampleFix":"// before\n@Inject @Intercepted Bean<MyService> self;\n// after\n@Inject @Intercepted Bean<?> self;","handlingStrategy":"validation","validationCode":"java.lang.reflect.Type t = MyInterceptor.class.getDeclaredField(\"bean\").getGenericType();\nboolean ok = t.getTypeName().equals(\"jakarta.enterprise.inject.spi.Bean<?>\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always declare @Intercepted injections as Bean<?> with unbound wildcard","Never use bounded wildcards or concrete types with @Intercepted","Remember the injection must also live in an interceptor class"],"tags":["cdi","arc","intercepted","wildcard","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"}