quarkusio/quarkus · error · WebSocketException
@%s callback may accept at most 1 message parameter; found %
Error message
@%s callback may accept at most 1 message parameter; found %s: %s
What it means
Message-handling callbacks (e.g. @OnTextMessage, @OnBinaryMessage) may accept at most one message parameter. When the callback accepts messages (acceptsMessage()) but more than one parameter qualifies as a message argument, the build fails with the annotation name, count, and signature.
Source
Thrown at extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java:1908
}
private static Callback findCallback(Target target, IndexView index, BeanInfo bean, ClassInfo beanClass,
DotName annotationName, CallbackArgumentsBuildItem callbackArguments,
TransformedAnnotationsBuildItem transformedAnnotations, String endpointPath,
Consumer<Callback> validator) {
List<AnnotationInstance> annotations = findCallbackAnnotations(index, beanClass, annotationName);
if (annotations.isEmpty()) {
return null;
} else if (annotations.size() == 1) {
AnnotationInstance annotation = annotations.get(0);
MethodInfo method = annotation.target().asMethod();
Callback callback = new Callback(target, annotation, bean, method,
executionModel(method, transformedAnnotations), callbackArguments, transformedAnnotations,
endpointPath, index);
long messageArguments = callback.arguments.stream().filter(ca -> ca instanceof MessageCallbackArgument).count();
if (callback.acceptsMessage()) {
if (messageArguments > 1) {
throw new WebSocketException(
String.format("@%s callback may accept at most 1 message parameter; found %s: %s",
DotNames.simpleName(callback.annotation.name()),
messageArguments,
callback.asString()));
}
} else {
if (messageArguments != 0) {
throw new WebSocketException(
String.format("@%s callback must not accept a message parameter; found %s: %s",
DotNames.simpleName(callback.annotation.name()),
messageArguments,
callback.asString()));
}
}
if (target == Target.CLIENT && callback.broadcast()) {
throw new WebSocketClientException(
String.format("@%s callback declared on a client endpoint must not broadcast messages: %s",
DotNames.simpleName(callback.annotation.name()),View on GitHub (pinned to e1c734241f)
Solutions
- Keep exactly one message parameter; move secondary data into method context types (WebSocketConnection, @PathParam, HttpHeaders)
- Wrap related fields into a single DTO and use one parameter (optionally with custom deserialization)
- Remove the redundant parameter
Example fix
// before
@OnTextMessage
void onMessage(String payload, String extra) {}
// after
class Msg { String payload; String extra; }
@OnTextMessage
void onMessage(Msg msg) {}
Defensive patterns
Strategy: validation
Validate before calling
// Message callbacks may have at most one message parameter
@OnTextMessage void onMessage(String msg) {} // single message slot Prevention
- Design one DTO per message type instead of multiple parameters
- Use WebSocketConnection/@PathParam/HttpHeaders for non-message data
- Review handler signatures after refactors
When it happens
Trigger: An @OnTextMessage or @OnBinaryMessage method declaring two or more message-typed parameters (e.g. two String parameters, or String plus a custom DTO).
Common situations: Developer expects a message plus metadata as a second message parameter; copy-paste duplicating a parameter; misunderstanding which parameters count as message arguments.
Related errors
- @OnPongMessage callback must return void or Uni<Void>:
- @OnPongMessage callback must accept exactly one message para
- @OnClose callback must return void or Uni<Void>:
- @OnError callback must accept exactly one error parameter; f
- @%s callback must not accept a message parameter; found %s:
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/436082081e9e844f.
Report an issue: GitHub.