{"record":{"id":"ab8ad3abd3b722f8","repo":"quarkusio/quarkus","slug":"event-type-contains-a-type-variable-specifiedty","errorCode":null,"errorMessage":"Event type contains a type variable: ${specifiedType}","messagePattern":"Event type contains a type variable: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/BeanManagerImpl.java","lineNumber":364,"sourceCode":"        }\n\n        if (!BeanTypeAssignabilityRules.instance().matches(requiredType, legalBeanTypes)) {\n            return false;\n        }\n        return ArcContainerImpl.instance().registeredQualifiers.hasQualifiers(beanQualifiers,\n                requiredQualifiers.toArray(new Annotation[0]));\n    }\n\n    @Override\n    public boolean isMatchingEvent(Type specifiedType, Set<Annotation> specifiedQualifiers, Type observedEventType,\n            Set<Annotation> observedEventQualifiers) {\n        illegalNull(specifiedType, \"specifiedType\");\n        illegalNull(specifiedQualifiers, \"specifiedQualifiers\");\n        illegalNull(observedEventType, \"observedEventType\");\n        illegalNull(observedEventQualifiers, \"observedEventQualifiers\");\n\n        if (Types.containsTypeVariable(specifiedType)) {\n            throw new IllegalArgumentException(\"Event type contains a type variable: \" + specifiedType);\n        }\n        ArcContainerImpl.instance().registeredQualifiers.verify(specifiedQualifiers);\n        ArcContainerImpl.instance().registeredQualifiers.verify(observedEventQualifiers);\n\n        Set<Annotation> eventQualifiers = new HashSet<>(specifiedQualifiers);\n        if (eventQualifiers.isEmpty()) {\n            eventQualifiers.add(Default.Literal.INSTANCE);\n        }\n        eventQualifiers.add(Any.Literal.INSTANCE);\n\n        Set<Type> eventTypes = new HierarchyDiscovery(specifiedType).getTypeClosure();\n        if (!EventTypeAssignabilityRules.instance().matches(observedEventType, eventTypes)) {\n            return false;\n        }\n        return ArcContainerImpl.instance().registeredQualifiers.isSubset(observedEventQualifiers, eventQualifiers);\n    }\n\n    private static void illegalNull(Object obj, String name) {","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/BeanManagerImpl.java#L346-L382","documentation":"The CDI Event.isMatching / event type check rejects a specifiedType containing type variables with IllegalArgumentException, since matching a type variable against an observed event type is undefined per spec. Qualifiers on both sides are verified as registered before the comparison proceeds.","triggerScenarios":"Calling event.isMatching(specifiedType, specifiedQualifiers, observedEventType, observedEventQualifiers) (or similar BeanManager event API) where specifiedType is a TypeVariable — typically a generic class's T or a wildcard-containing generic type obtained via reflection.","commonSituations":"Generic event-bus wrappers dispatching events for T; reflection frameworks passing getGenericType() results; meta-annotation/observer-introspection tooling written against generic classes.","solutions":["Pass a concrete Type (class, parameterized type with actual arguments) instead of the TypeVariable","Capture the concrete type with a TypeLiteral subclass before the call","Guard with Types.containsTypeVariable(specifiedType) and skip/throw a clearer error in your own code first"],"exampleFix":"// before\nType t = method.getGenericParameterTypes()[0]; // may be T\nbm.isMatching(t, quals, observedType, obsQuals);\n\n// after\nType t = new TypeLiteral<MyConcreteEvent>() {}.getType();\nbm.isMatching(t, quals, observedType, obsQuals);","handlingStrategy":"validation","validationCode":"if (Types.containsTypeVariable(specifiedType)) {\n    throw new IllegalArgumentException(\"specifiedType must be concrete: \" + specifiedType);\n}\nbm.isMatching(specifiedType, specifiedQualifiers, observedEventType, observedEventQualifiers);","typeGuard":"boolean isConcreteEventType(Type t) {\n    return !Types.containsTypeVariable(t);\n}","tryCatchPattern":"try {\n    return isMatching(specifiedType, sq, ot, oq);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"type variable\")) {\n        throw new IllegalStateException(\"Resolve specifiedType to a concrete Type first\");\n    } else throw e;\n}","preventionTips":["Never pass generic method/class type variables into event-matching APIs","Capture concrete types with TypeLiteral subclasses in generic event wrappers","Validate all Type arguments with Types.containsTypeVariable before CDI event calls"],"tags":["cdi","events","generics"],"backgroundTag":"illegal-type-variable","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"}