quarkusio/quarkus · error · DefinitionException
Decorator declares an async observer method: ${decoratorClas
Error message
Decorator declares an async observer method: ${decoratorClass} What it means
Build-time CDI definition error: a method in the decorator's class hierarchy has an @ObservesAsync parameter. Async observers are not allowed on decorators; ArC rejects the bean deployment naming the offending decorator class.
Source
Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Decorators.java:174
decoratedTypes, injections, priority);
}
private static void checkDecoratorFieldsAndMethods(ClassInfo decoratorClass, BeanDeployment beanDeployment) {
ClassInfo aClass = decoratorClass;
while (aClass != null) {
for (MethodInfo method : aClass.methods()) {
if (beanDeployment.hasAnnotation(method, DotNames.PRODUCES)) {
throw new DefinitionException("Decorator declares a producer method: " + decoratorClass);
}
// the following 3 checks rely on the annotation store returning parameter annotations for methods
if (beanDeployment.hasAnnotation(method, DotNames.DISPOSES)) {
throw new DefinitionException("Decorator declares a disposer method: " + decoratorClass);
}
if (beanDeployment.hasAnnotation(method, DotNames.OBSERVES)) {
throw new DefinitionException("Decorator declares an observer method: " + decoratorClass);
}
if (beanDeployment.hasAnnotation(method, DotNames.OBSERVES_ASYNC)) {
throw new DefinitionException("Decorator declares an async observer method: " + decoratorClass);
}
}
for (FieldInfo field : aClass.fields()) {
if (beanDeployment.hasAnnotation(field, DotNames.PRODUCES)) {
throw new DefinitionException("Decorator declares a producer field: " + decoratorClass);
}
}
DotName superClass = aClass.superName();
aClass = superClass != null && !superClass.equals(DotNames.OBJECT)
? getClassByName(beanDeployment.getBeanArchiveIndex(), superClass)
: null;
}
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Remove the @ObservesAsync method from the decorator.
- Move async observation to a dedicated observer bean.
- Keep the decorator focused on decorating the target interface only.
- Verify superclasses, as the validation includes inherited methods.
Example fix
// before
@Decorator
public class D implements Greeter {
void onTick(@ObservesAsync TickEvent e) { }
}
// after
@Decorator
public class D implements Greeter { /* observer moved out */ } Defensive patterns
Strategy: validation
Validate before calling
if (decoratorClass.getAnnotation(jakarta.decorator.Decorator.class) != null)
for (Method m : decoratorClass.getMethods())
if (m.isAnnotationPresent(jakarta.enterprise.event.ObservesAsync.class))
throw new IllegalStateException("Decorator cannot declare async observer: " + m); Prevention
- Move @ObservesAsync methods into dedicated observer beans.
- Audit decorators during reactive refactors for stray observer annotations.
When it happens
Trigger: A @Decorator class declares a method with an @ObservesAsync-annotated parameter, found by checkDecoratorFieldsAndMethods.
Common situations: Reactive refactor adding async observers onto a decorator; leftover @ObservesAsync after a class became a decorator; copying an async observer into the decorator.
Related errors
- Decorator declares an observer method: ${decoratorClass}
- Decorator declares a producer method: ${decoratorClass}
- Decorator declares a disposer method: ${decoratorClass}
- Decorator declares a producer field: ${decoratorClass}
- Disposer method must not have an @ObservesAsync parameter (a
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/6601c7a28c910438.
Report an issue: GitHub.