quarkusio/quarkus · error · IllegalArgumentException

Event type contains a type variable: ${specifiedType}

Error message

Event type contains a type variable: ${specifiedType}

What it means

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.

Source

Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/BeanManagerImpl.java:364

        }

        if (!BeanTypeAssignabilityRules.instance().matches(requiredType, legalBeanTypes)) {
            return false;
        }
        return ArcContainerImpl.instance().registeredQualifiers.hasQualifiers(beanQualifiers,
                requiredQualifiers.toArray(new Annotation[0]));
    }

    @Override
    public boolean isMatchingEvent(Type specifiedType, Set<Annotation> specifiedQualifiers, Type observedEventType,
            Set<Annotation> observedEventQualifiers) {
        illegalNull(specifiedType, "specifiedType");
        illegalNull(specifiedQualifiers, "specifiedQualifiers");
        illegalNull(observedEventType, "observedEventType");
        illegalNull(observedEventQualifiers, "observedEventQualifiers");

        if (Types.containsTypeVariable(specifiedType)) {
            throw new IllegalArgumentException("Event type contains a type variable: " + specifiedType);
        }
        ArcContainerImpl.instance().registeredQualifiers.verify(specifiedQualifiers);
        ArcContainerImpl.instance().registeredQualifiers.verify(observedEventQualifiers);

        Set<Annotation> eventQualifiers = new HashSet<>(specifiedQualifiers);
        if (eventQualifiers.isEmpty()) {
            eventQualifiers.add(Default.Literal.INSTANCE);
        }
        eventQualifiers.add(Any.Literal.INSTANCE);

        Set<Type> eventTypes = new HierarchyDiscovery(specifiedType).getTypeClosure();
        if (!EventTypeAssignabilityRules.instance().matches(observedEventType, eventTypes)) {
            return false;
        }
        return ArcContainerImpl.instance().registeredQualifiers.isSubset(observedEventQualifiers, eventQualifiers);
    }

    private static void illegalNull(Object obj, String name) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a concrete Type (class, parameterized type with actual arguments) instead of the TypeVariable
  2. Capture the concrete type with a TypeLiteral subclass before the call
  3. Guard with Types.containsTypeVariable(specifiedType) and skip/throw a clearer error in your own code first

Example fix

// before
Type t = method.getGenericParameterTypes()[0]; // may be T
bm.isMatching(t, quals, observedType, obsQuals);

// after
Type t = new TypeLiteral<MyConcreteEvent>() {}.getType();
bm.isMatching(t, quals, observedType, obsQuals);
Defensive patterns

Strategy: validation

Validate before calling

if (Types.containsTypeVariable(specifiedType)) {
    throw new IllegalArgumentException("specifiedType must be concrete: " + specifiedType);
}
bm.isMatching(specifiedType, specifiedQualifiers, observedEventType, observedEventQualifiers);

Type guard

boolean isConcreteEventType(Type t) {
    return !Types.containsTypeVariable(t);
}

Try / catch

try {
    return isMatching(specifiedType, sq, ot, oq);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("type variable")) {
        throw new IllegalStateException("Resolve specifiedType to a concrete Type first");
    } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Generic event-bus wrappers dispatching events for T; reflection frameworks passing getGenericType() results; meta-annotation/observer-introspection tooling written against generic classes.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/ab8ad3abd3b722f8. Report an issue: GitHub.