quarkusio/quarkus · error · IllegalArgumentException

Event#select(Class<U>, Annotation...) cannot be used with ty

Error message

Event#select(Class<U>, Annotation...) cannot be used with type variable parameter

What it means

EventImpl.select(Class<U>, Annotation...) — the CDI Event#select API — rejects a subtype parameter that still contains type variables (e.g. Class<T> where T is a generic type parameter of the enclosing method/class). The CDI spec forbids selecting on unresolved type variables because the resulting event type could not be resolved at runtime, so ArC throws IllegalArgumentException.

Source

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

                    @Override
                    public Notifier<? super T> apply(Class<?> clazz) {
                        return createNotifier(clazz);
                    }
                });
    }

    @Override
    public Event<T> select(Annotation... qualifiers) {
        ArcContainerImpl.instance().registeredQualifiers.verify(qualifiers);
        Set<Annotation> mergedQualifiers = new HashSet<>(this.qualifiers);
        Collections.addAll(mergedQualifiers, qualifiers);
        return new EventImpl<T>(eventType, mergedQualifiers, injectionPoint);
    }

    @Override
    public <U extends T> Event<U> select(Class<U> subtype, Annotation... qualifiers) {
        if (Types.containsTypeVariable(subtype)) {
            throw new IllegalArgumentException(
                    "Event#select(Class<U>, Annotation...) cannot be used with type variable parameter");
        }
        ArcContainerImpl.instance().registeredQualifiers.verify(qualifiers);
        Set<Annotation> mergerdQualifiers = new HashSet<>(this.qualifiers);
        Collections.addAll(mergerdQualifiers, qualifiers);
        return new EventImpl<U>(subtype, mergerdQualifiers, injectionPoint);
    }

    @Override
    public <U extends T> Event<U> select(TypeLiteral<U> subtype, Annotation... qualifiers) {
        ArcContainerImpl.instance().registeredQualifiers.verify(qualifiers);
        if (Types.containsTypeVariable(subtype.getType())) {
            throw new IllegalArgumentException(
                    "Event#select(TypeLiteral, Annotation...) cannot be used with type variable parameter");
        }
        Set<Annotation> mergerdQualifiers = new HashSet<>(this.qualifiers);
        Collections.addAll(mergerdQualifiers, qualifiers);
        return new EventImpl<U>(subtype.getType(), mergerdQualifiers, injectionPoint);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Use the concrete, non-generic class literal in select(), or reify the generic type with a TypeLiteral: event.select(new TypeLiteral<List<String>>() {}).
  2. Pass the runtime class via a constructor/parameter captured from the concrete subclass (getClass() at a non-generic call site).
  3. Move the select() call to a non-generic location where the type is fully known.
  4. If full runtime generic info is needed, use super type tokens (subclass anonymous TypeLiteral) rather than Class<T>.

Example fix

// before
class Publisher<T> {
  void fire(T payload) { event.select((Class<T>) payload.getClass()); } // may still contain type vars
}

// after
event.select(new TypeLiteral<MyConcretePayload>() {});
Defensive patterns

Strategy: type-guard

Validate before calling

if (Types.containsTypeVariable(subtype)) {
    throw new IllegalArgumentException("select() requires a fully resolved type, got " + subtype);
}

Type guard

static <T> boolean isConcreteEventType(Class<T> subtype) {
    return !io.quarkus.arc.impl.Types.containsTypeVariable(subtype);
}

Try / catch

try {
    event.select(subtypeClass);
} catch (IllegalArgumentException e) {
    if (!e.getMessage().contains("type variable parameter")) throw e;
    // fall back to a TypeLiteral-based select with a resolved type
}

Prevention

When it happens

Trigger: Inside a generic class/method, calling event.select(SomeGenericClass.class) where SomeGenericClass is itself generic and the class literal (e.g. T.class or ResultWrapper.class with T unresolved) contains type variables; the other select(TypeLiteral) overload throws its own analogous error.

Common situations: Generic helper/service classes wrapping CDI events where developers pass Class<T> fields obtained from generic APIs; refactoring an event publisher into a generic base class; Java's type erasure making Class<T> literals retain unresolved type variables.

Related errors


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