quarkusio/quarkus · error · IllegalArgumentException
The runtime type of the event object contains a type variabl
Error message
The runtime type of the event object contains a type variable: ${eventType} What it means
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.
Source
Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/BeanManagerImpl.java:139
public Bean<?> getPassivationCapableBean(String id) {
throw new UnsupportedOperationException();
}
@Override
public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans) {
return ArcContainerImpl.resolve(beans);
}
@Override
public void validate(InjectionPoint injectionPoint) {
throw new UnsupportedOperationException();
}
@Override
public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(T event, Annotation... qualifiers) {
Type eventType = Types.getCanonicalType(event.getClass());
if (Types.containsTypeVariable(eventType)) {
throw new IllegalArgumentException("The runtime type of the event object contains a type variable: " + eventType);
}
Set<Annotation> eventQualifiers = new HashSet<>(Arrays.asList(qualifiers));
return new LinkedHashSet<>(ArcContainerImpl.instance().resolveObserverMethods(eventType, eventQualifiers));
}
@Override
public List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers) {
return ArcContainerImpl.instance().resolveDecorators(types, qualifiers);
}
@Override
public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings) {
return ArcContainerImpl.instance().resolveInterceptors(Objects.requireNonNull(type), interceptorBindings);
}
@Override
public boolean isScope(Class<? extends Annotation> annotationType) {
return ArcContainerImpl.instance().isScope(annotationType);View on GitHub (pinned to e1c734241f)
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
Example fix
// before
Result<String> event = new Result<>();
bm.resolveObserverMethods(event); // canonical type still has T
// after
class StringResult extends Result<String> {}
bm.resolveObserverMethods(new StringResult()); Defensive patterns
Strategy: validation
Validate before calling
Type canonical = Types.getCanonicalType(event.getClass());
if (Types.containsTypeVariable(canonical)) {
throw new IllegalArgumentException("Event type must be concrete: " + canonical);
}
bm.resolveObserverMethods(event, qualifiers); Type guard
boolean isConcreteEventType(Class<?> eventClass) {
return !Types.containsTypeVariable(Types.getCanonicalType(eventClass));
} Try / catch
try {
return bm.resolveObserverMethods(event, quals);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("type variable")) {
throw new IllegalStateException("Use a concrete event subclass: " + event.getClass());
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Event injection point can never be raw type - please specify
- Event type contains a type variable: ${specifiedType}
- Event#select(Class<U>, Annotation...) cannot be used with ty
- Event#select(TypeLiteral, Annotation...) cannot be used with
- CDI event payload cannot contain unresolved type variable; f
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/7dc3e88257274cb3.
Report an issue: GitHub.