quarkusio/quarkus · error · IllegalArgumentException
Not a qualifier:
Error message
Not a qualifier:
What it means
ReceiverDefinitionImpl.setQualifiers validates that every supplied CDI annotation is actually a qualifier registered in the bean container. Passing a plain annotation (not a @Qualifier) would silently produce broken bean resolution, so it throws IllegalArgumentException.
Source
Thrown at extensions/signals/runtime/src/main/java/io/quarkus/signals/runtime/impl/ReceiverDefinitionImpl.java:41
private final Function<CallbackReceiver<SIGNAL, RESPONSE>, Receivers.Registration> registerFun;
private final BeanContainer beanContainer;
private final Type signalType;
private Set<Annotation> qualifiers = Set.of();
private ExecutionModel executionModel = ExecutionModel.BLOCKING;
public ReceiverDefinitionImpl(Type signalType, BeanContainer beanContainer,
Function<CallbackReceiver<SIGNAL, RESPONSE>, Receivers.Registration> registerFun) {
this.signalType = signalType;
this.beanContainer = beanContainer;
this.registerFun = registerFun;
}
@Override
public Receivers.ReceiverDefinition<SIGNAL> setQualifiers(Annotation... qualifiers) {
for (Annotation qualifier : qualifiers) {
if (!beanContainer.isQualifier(qualifier.annotationType())) {
throw new IllegalArgumentException("Not a qualifier: " + qualifier.annotationType().getName());
}
}
this.qualifiers = Set.of(qualifiers);
return this;
}
@Override
public Receivers.ReceiverDefinition<SIGNAL> setExecutionModel(ExecutionModel executionModel) {
this.executionModel = Objects.requireNonNull(executionModel);
return this;
}
@Override
public Registration notify(Consumer<SignalContext<SIGNAL>> callback) {
Objects.requireNonNull(callback);
@SuppressWarnings("unchecked")
CallbackReceiver<SIGNAL, RESPONSE> receiver = (CallbackReceiver<SIGNAL, RESPONSE>) new CallbackReceiver<>(
signalType, qualifiers, void.class, executionModel,View on GitHub (pinned to e1c734241f)
Solutions
- Only pass annotations meta-annotated with @jakarta.inject.Qualifier.
- Check the annotation's package/API (jakarta.enterprise vs javax or other) — use the CDI one the container knows.
- Register the custom qualifier properly or use a built-in qualifier like @Named or @Identifier.
Example fix
// before
@Retention(RUNTIME) @interface MyQ {} // not a qualifier
setQualifiers(new MyQ() { ... });
// after
@Qualifier @Retention(RUNTIME) @interface MyQ {}
setQualifiers(new MyQ() { ... }); Defensive patterns
Strategy: validation
Validate before calling
for (Annotation a : qualifiers) {
if (!a.annotationType().isAnnotationPresent(jakarta.inject.Qualifier.class)) {
throw new IllegalArgumentException(a.annotationType() + " is not a CDI qualifier");
}
} Prevention
- Meta-annotate every custom qualifier with @jakarta.inject.Qualifier.
- Prefer built-in qualifiers (@Named, @Identifier) when possible.
- Verify jakarta (not javax) imports in CDI code.
When it happens
Trigger: Calling receiverDefinition.setQualifiers(annotation...) with an annotation type not recognized as a CDI qualifier by the ArC bean container.
Common situations: Passing @jakarta.inject.Qualifier-less annotations, using annotations from the wrong injection API, or forgetting a @Qualifier meta-annotation on a custom annotation.
Related errors
- Multiple @Inject constructors on ${theClass}
- No datasource named '<dataSourceName>' exists
- Quarkus does not support CDI Full @Specializes annotation; t
- IllegalStateException wrapping ClassNotFoundException for ge
- Unable to derive the logger name at ${injectionPoint}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4980e1ccc0285378.
Report an issue: GitHub.