quarkusio/quarkus · error · java.lang.IllegalStateException

Route method that returns void must accept at least one inje

Error message

Route method that returns void must accept at least one injectable parameter [method: %s, bean: %s]

What it means

Raised by ReactiveRoutesProcessor.validateRouteMethod when a @Route-annotated business method returns void but declares no parameters the framework can inject. A void route method cannot produce a response body, so it must either end the response itself via an injectable parameter (e.g. RoutingContext) or otherwise consume the request; the surrounding validation walks the method signature (params.isEmpty() with VOID return) and rejects methods that could neither reply nor observe anything.

Source

Thrown at extensions/reactive-routes/deployment/src/main/java/io/quarkus/vertx/web/deployment/ReactiveRoutesProcessor.java:535

        if (!method.returnType().kind().equals(Type.Kind.VOID)) {
            throw new IllegalStateException(
                    String.format("Route filter method must return void [method: %s, bean: %s]", method, bean));
        }
        List<Type> params = method.parameterTypes();
        if (params.size() != 1 || !params.get(0).name()
                .equals(DotNames.ROUTING_CONTEXT)) {
            throw new IllegalStateException(String.format(
                    "Route filter method must accept exactly one parameter of type %s: %s [method: %s, bean: %s]",
                    DotNames.ROUTING_CONTEXT, params, method, bean));
        }
    }

    private void validateRouteMethod(BeanInfo bean, MethodInfo method,
            TransformedAnnotationsBuildItem transformedAnnotations, IndexView index, AnnotationInstance routeAnnotation) {
        List<Type> params = method.parameterTypes();
        if (params.isEmpty()) {
            if (method.returnType().kind() == Kind.VOID && params.isEmpty()) {
                throw new IllegalStateException(String.format(
                        "Route method that returns void must accept at least one injectable parameter [method: %s, bean: %s]",
                        method, bean));
            }
        } else {
            AnnotationValue typeValue = routeAnnotation.value(VALUE_TYPE);
            Route.HandlerType handlerType = typeValue == null
                    ? Route.HandlerType.NORMAL
                    : Route.HandlerType.from(typeValue.asEnum());

            DotName returnTypeName = method.returnType().name();

            if ((returnTypeName.equals(DotNames.UNI)
                    || returnTypeName.equals(DotNames.MULTI)
                    || returnTypeName.equals(DotNames.COMPLETION_STAGE))
                    && method.returnType().kind() == Kind.CLASS) {
                throw new IllegalStateException(String.format(
                        "Route business method returning a Uni/Multi/CompletionStage must declare a type argument on the return type [method: %s, bean: %s]",
                        method, bean));

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add an injectable parameter such as io.vertx.ext.web.RoutingContext to the route method so it can end the response
  2. Return a value (e.g. String, Uni<String>) from the method instead of void
  3. Annotate the method as a filter-style handler correctly (@Route with proper handler type) if that was intended
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at extensions/reactive-routes/deployment/src/main/java/io/quarkus/vertx/web/deployment/ReactiveRoutesProcessor.java:535 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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