quarkusio/quarkus · error · DefinitionException
Bean constructor must not have an @ObservesAsync parameter:
Error message
Bean constructor must not have an @ObservesAsync parameter:
What it means
ArC throws this DefinitionException at build time when a bean constructor has a parameter annotated with @ObservesAsync. Async observer parameters are only valid on observer methods, never on constructors. Injection.forBean checks constructor parameters against OBSERVES_ASYNC and rejects the bean definition.
Source
Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java:238
if (injectConstructors.size() > 1) {
throw new DefinitionException(
"Multiple @Inject constructors found on " + beanTarget.asClass().name() + ":\n"
+ injectConstructors.stream().map(Object::toString).collect(Collectors.joining("\n")));
}
for (AnnotationTarget injectConstructor : injectConstructors) {
Set<AnnotationInstance> parameterAnnotations = Annotations.getParameterAnnotations(beanDeployment,
injectConstructor.asMethod());
for (AnnotationInstance annotation : parameterAnnotations) {
if (DotNames.DISPOSES.equals(annotation.name())) {
throw new DefinitionException(
"Bean constructor must not have a @Disposes parameter: " + injectConstructor);
}
if (DotNames.OBSERVES.equals(annotation.name())) {
throw new DefinitionException(
"Bean constructor must not have an @Observes parameter: " + injectConstructor);
}
if (DotNames.OBSERVES_ASYNC.equals(annotation.name())) {
throw new DefinitionException(
"Bean constructor must not have an @ObservesAsync parameter: " + injectConstructor);
}
}
}
Set<MethodInfo> initializerMethods = injections.stream()
.filter(it -> it.isMethod() && !it.isConstructor())
.map(Injection::getTarget)
.map(AnnotationTarget::asMethod)
.collect(Collectors.toSet());
for (MethodInfo initializerMethod : initializerMethods) {
if (beanDeployment.hasAnnotation(initializerMethod, DotNames.PRODUCES)) {
throw new DefinitionException("Initializer method must not be annotated @Produces "
+ "(alternatively, producer method must not be annotated @Inject): "
+ beanTarget.asClass() + "." + initializerMethod.name());
}
if (Annotations.hasParameterAnnotation(beanDeployment, initializerMethod, DotNames.DISPOSES)) {
throw new DefinitionException("Initializer method must not have a @Disposes parameter "View on GitHub (pinned to e1c734241f)
Solutions
- Remove @ObservesAsync from the constructor parameter
- Move async event handling into a dedicated method: void onEvent(@ObservesAsync MyEvent e) { ... }
- Use CompletionStage/Uni-based handling inside an observer method instead of the constructor
- Rebuild after fixing; error occurs during augmentation
Example fix
// before
@Inject
MyBean(@ObservesAsync TaskEvent e) { ... }
// after
@Inject
MyBean() { }
void onTask(@ObservesAsync TaskEvent e) { ... } Defensive patterns
Strategy: validation
Validate before calling
void checkConstructor(Method ctor) throws Exception {
for (var p : ctor.getParameters()) {
if (p.isAnnotationPresent(jakarta.enterprise.event.ObservesAsync.class)) {
throw new IllegalStateException("@ObservesAsync on constructor param: " + ctor);
}
}
} Prevention
- Use @ObservesAsync only on dedicated observer methods
- Remember async observers return void/CompletionStage, never appear on constructors
- Keep constructor signatures free of event annotations
- Compile early and often — ArC catches these during augmentation
When it happens
Trigger: Annotating a bean constructor parameter with @jakarta.enterprise.event.ObservesAsync, detected while ArC iterates parameter annotations of inject constructors in forBean.
Common situations: Confusing @ObservesAsync with @Observes when wiring async event handling into bean creation; refactoring an async observer method into a constructor; copy-paste from a listener class.
Related errors
- Initializer method must not have an @ObservesAsync parameter
- Bean constructor must not have a @Disposes parameter:
- Bean constructor must not have an @Observes parameter:
- Initializer method must not be annotated @Produces (alternat
- Initializer method must not have a @Disposes parameter (alte
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/16d31a35f436b3df.
Report an issue: GitHub.