{"record":{"id":"7dc3e88257274cb3","repo":"quarkusio/quarkus","slug":"the-runtime-type-of-the-event-object-contains-a-ty","errorCode":null,"errorMessage":"The runtime type of the event object contains a type variable: ${eventType}","messagePattern":"The runtime type of the event object 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":139,"sourceCode":"    public Bean<?> getPassivationCapableBean(String id) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans) {\n        return ArcContainerImpl.resolve(beans);\n    }\n\n    @Override\n    public void validate(InjectionPoint injectionPoint) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(T event, Annotation... qualifiers) {\n        Type eventType = Types.getCanonicalType(event.getClass());\n        if (Types.containsTypeVariable(eventType)) {\n            throw new IllegalArgumentException(\"The runtime type of the event object contains a type variable: \" + eventType);\n        }\n        Set<Annotation> eventQualifiers = new HashSet<>(Arrays.asList(qualifiers));\n        return new LinkedHashSet<>(ArcContainerImpl.instance().resolveObserverMethods(eventType, eventQualifiers));\n    }\n\n    @Override\n    public List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers) {\n        return ArcContainerImpl.instance().resolveDecorators(types, qualifiers);\n    }\n\n    @Override\n    public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings) {\n        return ArcContainerImpl.instance().resolveInterceptors(Objects.requireNonNull(type), interceptorBindings);\n    }\n\n    @Override\n    public boolean isScope(Class<? extends Annotation> annotationType) {\n        return ArcContainerImpl.instance().isScope(annotationType);","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/BeanManagerImpl.java#L121-L157","documentation":"BeanManagerImpl.resolveObserverMethods(T event, ...) computes the canonical runtime type of the event object and rejects it if that type still contains a type variable. The CDI spec forbids resolving observer methods for event types with unresolved type variables, because assignability would be ill-defined.","triggerScenarios":"Calling resolveObserverMethods with an instance whose runtime class is generic (e.g. Result<String>.class erasure path) or instantiating a raw/parameterized generic class and passing it; Types.getCanonicalType resolving to a type containing TypeVariables.","commonSituations":"Firing/resolving events of generic DTO wrapper types; reflection-driven event dispatch in custom frameworks; subclassing a generic event base class and passing an instance whose canonical type keeps T.","solutions":["Use a concrete, non-generic event class (create a named subclass, e.g. class StringResult extends Result<String> {})","Pass a non-generic payload (wrap generics in a concrete type or use a raw concrete class)","Guard with Types.containsTypeVariable(Types.getCanonicalType(event.getClass())) before the call"],"exampleFix":"// before\nResult<String> event = new Result<>();\nbm.resolveObserverMethods(event); // canonical type still has T\n\n// after\nclass StringResult extends Result<String> {}\nbm.resolveObserverMethods(new StringResult());","handlingStrategy":"validation","validationCode":"Type canonical = Types.getCanonicalType(event.getClass());\nif (Types.containsTypeVariable(canonical)) {\n    throw new IllegalArgumentException(\"Event type must be concrete: \" + canonical);\n}\nbm.resolveObserverMethods(event, qualifiers);","typeGuard":"boolean isConcreteEventType(Class<?> eventClass) {\n    return !Types.containsTypeVariable(Types.getCanonicalType(eventClass));\n}","tryCatchPattern":"try {\n    return bm.resolveObserverMethods(event, quals);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"type variable\")) {\n        throw new IllegalStateException(\"Use a concrete event subclass: \" + event.getClass());\n    } else throw e;\n}","preventionTips":["Design events as concrete (non-generic) classes","If payloads are generic, create named subclasses (class FooEvent extends Event<Foo> {})","Never fire events of raw generic types from reflection-driven code"],"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-14T00:17:10.932Z"}