quarkusio/quarkus · error · WebSocketServerException
The endpoint must declare at least one method annotated with
Error message
The endpoint must declare at least one method annotated with @OnTextMessage, @OnBinaryMessage, @OnPingMessage, @OnPongMessage or @OnOpen:
What it means
An endpoint that has no @OnOpen, @OnTextMessage, @OnBinaryMessage, @OnPingMessage or @OnPongMessage method can never receive or process anything meaningful, so Quarkus rejects the deployment. @OnClose alone is not sufficient.
Source
Thrown at extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java:419
Callback onOpen = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_OPEN, callbackArguments, transformedAnnotations, path);
Callback onTextMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_TEXT_MESSAGE, callbackArguments, transformedAnnotations, path);
Callback onBinaryMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_BINARY_MESSAGE, callbackArguments, transformedAnnotations, path);
Callback onPingMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_PING_MESSAGE, callbackArguments, transformedAnnotations, path,
this::validateOnPingMessage);
Callback onPongMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_PONG_MESSAGE, callbackArguments, transformedAnnotations, path,
this::validateOnPongMessage);
Callback onClose = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_CLOSE, callbackArguments, transformedAnnotations, path,
this::validateOnClose);
if (onOpen == null && onTextMessage == null && onBinaryMessage == null && onPingMessage == null
&& onPongMessage == null) {
throw new WebSocketServerException(
"The endpoint must declare at least one method annotated with @OnTextMessage, @OnBinaryMessage, @OnPingMessage, @OnPongMessage or @OnOpen: "
+ beanClass);
}
if (onTextMessage != null) {
Type effectiveMessageType;
if (onTextMessage.isKotlinSuspendFunction()) {
effectiveMessageType = onTextMessage.isReturnTypeUni()
? onTextMessage.returnType().asParameterizedType().arguments().get(0)
: KotlinUtils.getKotlinSuspendMethodResult(onTextMessage.method);
} else if (onTextMessage.isReturnTypeUni() || onTextMessage.isReturnTypeMulti()) {
effectiveMessageType = onTextMessage.returnType().asParameterizedType().arguments().get(0);
} else {
effectiveMessageType = onTextMessage.returnType();
}
if (effectiveMessageType.kind() != Type.Kind.VOID && onTextMessage.getOutputCodec() == null) {
reflectiveHierarchy
.produce(ReflectiveHierarchyBuildItem.builder(effectiveMessageType).build());
}View on GitHub (pinned to e1c734241f)
Solutions
- Add at least one message callback, typically @OnTextMessage or @OnBinaryMessage
- Or add @OnOpen if the endpoint only needs to react to connection opening
- Verify the annotations used are from io.quarkus.websockets.next, not another package
Example fix
// before
@WebSocket(path="/ws")
class MyWs { @OnClose void close() {} }
// after
@WebSocket(path="/ws")
class MyWs {
@OnTextMessage void onMessage(String msg) {}
@OnClose void close() {}
} Defensive patterns
Strategy: validation
Validate before calling
@Test
void endpointHasHandler(Class<?> endpoint) {
for (Method m : endpoint.getDeclaredMethods()) {
for (Class<?> ann : List.of(OnOpen.class, OnTextMessage.class, OnBinaryMessage.class,
OnPingMessage.class, OnPongMessage.class)) {
if (m.isAnnotationPresent(ann)) return;
}
}
throw new AssertionError(endpoint + " lacks @OnOpen or message handlers");
} Prevention
- Start new endpoints from a template that includes @OnTextMessage
- Verify annotation imports resolve to io.quarkus.websockets.next.*
- Never leave a handler-only-@OnClose stub in committed code
When it happens
Trigger: Declaring a @WebSocket/@WebSocketClient class whose only callback is @OnClose (or which has no message callbacks at all).
Common situations: Starting with a skeleton endpoint before writing handlers; accidentally deleting/commenting-out the message methods during refactoring; wrong annotation imports (e.g. jakarta annotations not from io.quarkus.websockets.next) so the processor does not see them.
Related errors
- Endpoint class may not be annotated with both @WebSocket and
- The configuration ${clazz} is missing the @ConfigRoot annota
- Annotation instance ${annotationInstance} does not match ann
- Unknown value of annotation member ${name}
- Method ${method} not implemented
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/a14c42bb8f6dee43.
Report an issue: GitHub.