quarkusio/quarkus · error · IllegalStateException

@ExceptionHandler methods in @ControllerAdvice classes can o

Error message

@ExceptionHandler methods in @ControllerAdvice classes can only have void, ResponseEntity or POJO return types

What it means

The generated JAX-RS ExceptionMapper must know how to write the response body. @ExceptionHandler methods returning unsupported types (per DISALLOWED_EXCEPTION_CONTROLLER_RETURN_TYPES, e.g. Spring Model/View types Quarkus can't render) are rejected at build time. Only void, ResponseEntity, or serializable POJO return types are supported.

Source

Thrown at extensions/spring-web/core/deployment/src/main/java/io/quarkus/spring/web/deployment/SpringWebProcessor.java:222

            return;
        }

        ClassInfo controllerAdvice = controllerAdviceInstance.target().asClass();
        List<MethodInfo> methods = controllerAdvice.methods();
        for (MethodInfo method : methods) {
            AnnotationInstance exceptionHandlerInstance = method.annotation(EXCEPTION_HANDLER);
            if (exceptionHandlerInstance == null) {
                continue;
            }

            if (!Modifier.isPublic(method.flags()) || Modifier.isStatic(method.flags())) {
                throw new IllegalStateException(
                        "@ExceptionHandler methods in @ControllerAdvice must be public instance methods");
            }

            DotName returnTypeDotName = method.returnType().name();
            if (DISALLOWED_EXCEPTION_CONTROLLER_RETURN_TYPES.contains(returnTypeDotName)) {
                throw new IllegalStateException(
                        "@ExceptionHandler methods in @ControllerAdvice classes can only have void, ResponseEntity or POJO return types");
            }

            if (!RESPONSE_ENTITY.equals(returnTypeDotName)) {
                reflectiveClassProducer.produce(
                        ReflectiveClassBuildItem.builder(returnTypeDotName.toString()).methods().fields().build());
            }

            // we need to generate one JAX-RS ExceptionMapper per Exception type
            Type[] handledExceptionTypes = exceptionHandlerInstance.value().asClassArray();
            for (Type handledExceptionType : handledExceptionTypes) {
                reflectiveClassProducer.produce(
                        ReflectiveClassBuildItem.builder(method.declaringClass().toString()).constructors(false).build());
                String name = new ControllerAdviceExceptionMapperGenerator(method, handledExceptionType.name(),
                        classOutput, typesUtil, isResteasyClassic).generate();
                providersProducer.produce(new ResteasyJaxrsProviderBuildItem(name));
                exceptionMapperProducer.produce(
                        new ExceptionMapperBuildItem(name, handledExceptionType.name().toString(), Priorities.USER, false));

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the return type to ResponseEntity<T> or a plain POJO that Jackson can serialize.
  2. Return void if the response body isn't needed (status from @ResponseStatus or the exception).
  3. Replace view-model logic with building a JSON DTO and returning it via ResponseEntity.

Example fix

// before
@ExceptionHandler(MyException.class)
public ModelAndView handle(MyException e) { return new ModelAndView("error"); }

// after
@ExceptionHandler(MyException.class)
public ResponseEntity<ErrorDto> handle(MyException e) {
  return ResponseEntity.status(422).body(new ErrorDto(e.getMessage()));
}
Defensive patterns

Strategy: validation

Validate before calling

// allowed return types: void, ResponseEntity<T>, serializable POJO
// reject at code review: ModelAndView, Model, View, Servlet objects

Prevention

When it happens

Trigger: An @ExceptionHandler method in a @ControllerAdvice returns a type like ModelAndView, Model, View, or another disallowed Spring web type.

Common situations: Migrating Spring MVC code that renders views (Thymeleaf/JSP style) to Quarkus; handlers returning raw Servlet objects copied from legacy code.

Related errors


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