quarkusio/quarkus · error · RuntimeException

The combination of '@${annotationName}' and '@ServerExceptio

Error message

The combination of '@${annotationName}' and '@ServerExceptionMapper' is not allowed. Offending method is '${methodName}' of class '${className}'

What it means

Quarkus REST rejects combining bean-conditional annotations (@IfBuildProfile, @IfBuildProperty, etc.) with @ServerExceptionMapper. During deployment, exception mappers are generated into beans, and a method-level conditional annotation cannot be honored, so the build fails fast with the offending method and class named.

Source

Thrown at extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveScanningProcessor.java:509

                continue;
            }
            MethodInfo methodInfo = instance.target().asMethod();
            if (methodInfo.isBridge()) { // we don't want to generate duplicates for bridge methods added by javac to handle generics
                continue;
            }
            if (classLevelExceptionMappers.contains(methodInfo)) { // methods annotated with @ServerExceptionMapper that exist inside a Resource Class are handled differently
                continue;
            }
            // the user class itself is made to be a bean as we want the user to be able to declare dependencies
            additionalBeans.addBeanClass(methodInfo.declaringClass().name().toString());
            Map<String, String> generatedClassNames = ServerExceptionMapperGenerator.generateGlobalMapper(methodInfo,
                    new GeneratedBeanGizmoAdaptor(generatedBean),
                    Set.of(HTTP_SERVER_REQUEST, HTTP_SERVER_RESPONSE, ROUTING_CONTEXT), Set.of(Unremovable.class.getName()),
                    (m -> {
                        List<AnnotationInstance> methodAnnotations = m.annotations();
                        for (AnnotationInstance methodAnnotation : methodAnnotations) {
                            if (CONDITIONAL_BEAN_ANNOTATIONS.contains(methodAnnotation.name())) {
                                throw new RuntimeException(
                                        "The combination of '@" + methodAnnotation.name().withoutPackagePrefix()
                                                + "' and '@ServerExceptionMapper' is not allowed. Offending method is '"
                                                + m.name() + "' of class '" + m.declaringClass().name() + "'");
                            }
                        }

                        List<AnnotationInstance> classAnnotations = m.declaringClass().declaredAnnotations();
                        for (AnnotationInstance classAnnotation : classAnnotations) {
                            if (CONDITIONAL_BEAN_ANNOTATIONS.contains(classAnnotation.name())) {
                                return true;
                            }
                        }
                        return false;
                    }));
            for (Map.Entry<String, String> entry : generatedClassNames.entrySet()) {
                ExceptionMapperBuildItem.Builder builder = new ExceptionMapperBuildItem.Builder(entry.getValue(),
                        entry.getKey())
                        .setRegisterAsBean(false) // it has already been made a bean

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the conditional annotation from the @ServerExceptionMapper method
  2. Move the conditional annotation to the declaring class level
  3. Use a plain CDI ExceptionMapper<...> bean with the conditional annotation instead
  4. Duplicate the mapper across profiles using quarkus.* build-time properties via separate generated classes

Example fix

// before
@IfBuildProperty(name = "app.sec", stringValue = "on")
@ServerExceptionMapper
public Response map(SecurityException e) { ... }
// after: class-level condition
@IfBuildProperty(name = "app.sec", stringValue = "on")
public class SecMappers {
    @ServerExceptionMapper
    public Response map(SecurityException e) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

// build-time check: no conditional annotations on exception mapper methods
for (AnnotationInstance a : m.annotations()) {
    if (CONDITIONAL_BEAN_ANNOTATIONS.contains(a.name())) {
        throw new IllegalArgumentException("Remove " + a + " from @ServerExceptionMapper method " + m.name());
    }
}

Prevention

When it happens

Trigger: Declaring a method annotated with @ServerExceptionMapper that also carries one of CONDITIONAL_BEAN_ANNOTATIONS (e.g. @IfBuildProfile, @IfBuildProperty) on the same method.

Common situations: Trying to activate an exception mapper only under a build profile or build property; copying a mapper from a CDI-based class while retaining its profile annotations.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/b5dc4e14e3166b3a. Report an issue: GitHub.