quarkusio/quarkus · error · RuntimeException
Method '${targetMethod.name()} of class '${targetMethod.decl
Error message
Method '${targetMethod.name()} of class '${targetMethod.declaringClass().name()}' cannot be used as an exception mapper as it does not declare 'Response' or 'Uni<Response>' or as its return type What it means
RESTEasy Reactive's build-time generator scans methods annotated with @ServerExceptionMapper / @Provider and requires a supported return type: 'Response', 'RestResponse', 'Uni<Response>' (or Uni<RestResponse>). In determineReturnType, if no branch matches the method's return type, a RuntimeException is thrown, aborting application build. This enforces that exception mappers actually produce an HTTP response that can be returned to the client.
Source
Thrown at independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/generation/exceptionmappers/ServerExceptionMapperGenerator.java:634
}
private static ReturnType determineReturnType(MethodInfo targetMethod) {
if (targetMethod.returnType().name().equals(RESPONSE)) {
return ReturnType.RESPONSE;
} else if (targetMethod.returnType().name().equals(REST_RESPONSE)) {
return ReturnType.REST_RESPONSE;
} else if (targetMethod.returnType().kind() == Type.Kind.PARAMETERIZED_TYPE) {
ParameterizedType parameterizedType = targetMethod.returnType().asParameterizedType();
if (parameterizedType.name().equals(UNI) && (parameterizedType.arguments().size() == 1)) {
if (parameterizedType.arguments().get(0).name().equals(RESPONSE)) {
return ReturnType.UNI_RESPONSE;
}
if (parameterizedType.arguments().get(0).name().equals(REST_RESPONSE)) {
return ReturnType.UNI_REST_RESPONSE;
}
}
}
throw new RuntimeException("Method '" + targetMethod.name() + " of class '" + targetMethod.declaringClass().name()
+ "' cannot be used as an exception mapper as it does not declare 'Response' or 'Uni<Response>' or as its return type");
}
private static void checkModifiers(MethodInfo info) {
if ((info.flags() & Modifier.PRIVATE) != 0) {
throw new RuntimeException("Method '" + info.name() + " of class '" + info.declaringClass().name()
+ "' cannot be private as it is annotated with '@" + SERVER_EXCEPTION_MAPPER
+ "'");
}
if ((info.flags() & Modifier.STATIC) != 0) {
throw new RuntimeException("Method '" + info.name() + " of class '" + info.declaringClass().name()
+ "' cannot be static as it is annotated with '@" + SERVER_EXCEPTION_MAPPER
+ "'");
}
}
private static String getGeneratedClassName(MethodInfo targetMethod, Type handledExceptionType) {
return targetMethod.declaringClass().name() + "$ExceptionMapper$"View on GitHub (pinned to e1c734241f)
Solutions
- Change the mapper method return type to jakarta.ws.rs.core.Response
- Or return io.smallrye.mutiny.Uni<Response> for asynchronous mapping
- Or return jakarta.ws.rs.core.RestResponse if using the RESTEasy Reactive API
- Remove @ServerExceptionMapper/@Provider from methods that are not intended to be exception mappers
Example fix
// before
@ServerExceptionMapper
public String map(IllegalStateException e) { return e.getMessage(); }
// after
@ServerExceptionMapper
public Response map(IllegalStateException e) { return Response.status(500).entity(e.getMessage()).build(); } Defensive patterns
Strategy: validation
Validate before calling
java.lang.reflect.Method m = ...; // the annotated mapper
boolean ok = Response.class.equals(m.getReturnType())
|| RestResponse.class.equals(m.getReturnType())
|| (m.getReturnType() == Uni.class && m.getGenericReturnType() instanceof ParameterizedType pt
&& Response.class.equals(pt.getActualTypeArguments()[0]));
if (!ok) throw new IllegalStateException("Mapper must return Response, RestResponse, or Uni<Response>: " + m);
Type guard
static boolean isValidMapperReturn(java.lang.reflect.Method m) {
return Response.class.equals(m.getReturnType()) || RestResponse.class.equals(m.getReturnType())
|| (m.getReturnType() == Uni.class
&& m.getGenericReturnType() instanceof ParameterizedType pt
&& (Response.class.equals(pt.getActualTypeArguments()[0]) || RestResponse.class.equals(pt.getActualTypeArguments()[0])));
}
Prevention
- Always declare @ServerExceptionMapper methods to return Response or Uni<Response>
- Never put @Provider on non-mapper helper methods
- Let your IDE annotate only methods returning Response; add an ArchUnit/architectural test scanning mapper signatures
- Run a quick mvn compile of the extension/module before pushing — the error surfaces at build time
When it happens
Trigger: Annotating a method with @ServerExceptionMapper (or @Provider recognized as a server exception mapper) whose return type is anything other than Response, RestResponse, Uni<Response>, or Uni<RestResponse> — e.g. void, String, MyPojo, CompletionStage<Response> — triggers the error during Quarkus augmentation.
Common situations: Developers migrating from classic JAX-RS ExceptionMapper semantics, writing a mapper that logs and returns void, returning a custom DTO instead of Response, or accidentally annotating an ordinary helper method with @Provider in a scanned package.
Related errors
- The combination of '@${annotationName}' and '@ServerExceptio
- The combination of '@${annotationName}' and '@ServerRequestF
- Usage of multiple methods using '@RequestMapping' is not all
- Unsupported HTTP method '<method>' for @RequestMapping. Offe
- Endpoint return type not supported yet: ${paramType}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/14085a38a545aa84.
Report an issue: GitHub.