{"record":{"id":"84bdb56e082137e1","repo":"quarkusio/quarkus","slug":"you-can-only-have-a-single-class-annotated-with-c","errorCode":null,"errorMessage":"You can only have a single class annotated with @ControllerAdvice","messagePattern":"You can only have a single class annotated with @ControllerAdvice","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/spring-web/core/deployment/src/main/java/io/quarkus/spring/web/deployment/SpringWebProcessor.java","lineNumber":261,"sourceCode":"        }\n\n        // allow access to HttpHeaders from Arc.container()\n        if (!isResteasyClassic) {\n            unremovableBeanProducer.produce(\n                    UnremovableBeanBuildItem.beanClassNames(\"org.jboss.resteasy.reactive.server.injection.ContextProducers\",\n                            HttpHeaders.class.getName()));\n        }\n    }\n\n    private AnnotationInstance getSingleControllerAdviceInstance(IndexView index) {\n        Collection<AnnotationInstance> controllerAdviceInstances = index.getAnnotations(REST_CONTROLLER_ADVICE);\n\n        if (controllerAdviceInstances.isEmpty()) {\n            return null;\n        }\n\n        if (controllerAdviceInstances.size() > 1) {\n            throw new IllegalStateException(\"You can only have a single class annotated with @ControllerAdvice\");\n        }\n\n        return controllerAdviceInstances.iterator().next();\n    }\n\n}\n","sourceCodeStart":243,"sourceCodeEnd":268,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spring-web/core/deployment/src/main/java/io/quarkus/spring/web/deployment/SpringWebProcessor.java#L243-L268","documentation":"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.","triggerScenarios":"Two or more classes annotated with @ControllerAdvice in the application, detected during the controllerAdviceSupport build step.","commonSituations":"Merging modules that each brought their own advice class; adding a new advice without deleting the demo/template one; splitting exception handling across teams.","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."],"exampleFix":"// before\n@ControllerAdvice class GlobalAdvice { ... }\n@ControllerAdvice class PaymentAdvice { ... }\n\n// after: merge into one\n@ControllerAdvice class GlobalAdvice {\n  @ExceptionHandler(PaymentException.class) ...\n  @ExceptionHandler(IllegalArgumentException.class) ...\n}","handlingStrategy":"validation","validationCode":"// enforce a single advice class, e.g. an ArchUnit/test check:\n// assertThat(classesAnnotatedWith(ControllerAdvice.class)).hasSize(1);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep exactly one @ControllerAdvice class per application, ideally named GlobalExceptionHandler.","When merging modules, consolidate exception handling instead of keeping per-module advice."],"tags":["quarkus","spring-web","controlleradvice","build-time"],"backgroundTag":"duplicate-bean-definition","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}