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
- Add an injectable parameter such as io.vertx.ext.web.RoutingContext to the route method so it can end the response
- Return a value (e.g. String, Uni<String>) from the method instead of void
- 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.