quarkusio/quarkus · error · IllegalStateException
You can only have a single class annotated with @ControllerA
Error message
You can only have a single class annotated with @ControllerAdvice
What it means
Quarkus's Spring Web support builds a single, global ExceptionMapper set from one @ControllerAdvice class (matching Spring's ability to have one precedence-winning advice, but implemented more strictly). If more than one class is annotated @ControllerAdvice, the build fails because the processor cannot pick a winner.
Source
Thrown at extensions/spring-web/core/deployment/src/main/java/io/quarkus/spring/web/deployment/SpringWebProcessor.java:261
}
// allow access to HttpHeaders from Arc.container()
if (!isResteasyClassic) {
unremovableBeanProducer.produce(
UnremovableBeanBuildItem.beanClassNames("org.jboss.resteasy.reactive.server.injection.ContextProducers",
HttpHeaders.class.getName()));
}
}
private AnnotationInstance getSingleControllerAdviceInstance(IndexView index) {
Collection<AnnotationInstance> controllerAdviceInstances = index.getAnnotations(REST_CONTROLLER_ADVICE);
if (controllerAdviceInstances.isEmpty()) {
return null;
}
if (controllerAdviceInstances.size() > 1) {
throw new IllegalStateException("You can only have a single class annotated with @ControllerAdvice");
}
return controllerAdviceInstances.iterator().next();
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Merge the @ExceptionHandler methods of all @ControllerAdvice classes into a single class.
- Remove @ControllerAdvice from redundant classes (plain classes don't need it).
- Use @Priority-aware JAX-RS ExceptionMappers directly for fine-grained per-exception handling instead.
Example fix
// before
@ControllerAdvice class GlobalAdvice { ... }
@ControllerAdvice class PaymentAdvice { ... }
// after: merge into one
@ControllerAdvice class GlobalAdvice {
@ExceptionHandler(PaymentException.class) ...
@ExceptionHandler(IllegalArgumentException.class) ...
} Defensive patterns
Strategy: validation
Validate before calling
// enforce a single advice class, e.g. an ArchUnit/test check: // assertThat(classesAnnotatedWith(ControllerAdvice.class)).hasSize(1);
Prevention
- Keep exactly one @ControllerAdvice class per application, ideally named GlobalExceptionHandler.
- When merging modules, consolidate exception handling instead of keeping per-module advice.
When it happens
Trigger: Two or more classes annotated with @ControllerAdvice in the application, detected during the controllerAdviceSupport build step.
Common situations: Merging modules that each brought their own advice class; adding a new advice without deleting the demo/template one; splitting exception handling across teams.
Related errors
- Parameter type <type> is being used multiple times in method
- Parameter type <type> is not supported for method<method> of
- Parameter type '<type>' is not supported for method '<method
- @ExceptionHandler methods in @ControllerAdvice must be publi
- Spring Web can only work if 'quarkus-resteasy-jackson' or 'q
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/84bdb56e082137e1.
Report an issue: GitHub.