quarkusio/quarkus · error · WebSocketClientException

@%s callback declared on a client endpoint must not broadcas

Error message

@%s callback declared on a client endpoint must not broadcast messages: %s

What it means

WebSockets Next throws this WebSocketClientException during build-time validation when a callback method on a @WebSocketClient endpoint (Target.CLIENT) is annotated to broadcast messages (e.g. @OnTextMessage(broadcast = true) or a BroadcastSender parameter usage). Broadcasting only makes sense for server endpoints, which can push a message to all connected clients; a client endpoint has only a single connection to the server.

Source

Thrown at extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java:1924

            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()),
                                callback.asString()));
            }
            if (validator != null) {
                validator.accept(callback);
            }
            return callback;
        }
        throw new WebSocketException(
                String.format("There can be only one callback annotated with %s declared on %s", annotationName, beanClass));
    }

    private static ExecutionModel executionModel(MethodInfo method, TransformedAnnotationsBuildItem transformedAnnotations) {
        if (KotlinUtils.isKotlinSuspendMethod(method)
                && (transformedAnnotations.hasAnnotation(method, WebSocketDotNames.RUN_ON_VIRTUAL_THREAD)
                        || transformedAnnotations.hasAnnotation(method.declaringClass(),
                                WebSocketDotNames.RUN_ON_VIRTUAL_THREAD)

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove broadcast = true (and any BroadcastSender parameter) from callbacks on the client endpoint class
  2. Use OnTextMessage/OnBinaryMessage without broadcast on the client, processing the single inbound message directly
  3. If fan-out to multiple server sessions is needed, that logic belongs on the server endpoint, not the client

Example fix

// before
@WebSocketClient(path = "/client")
class MyClient {
    @OnTextMessage(broadcast = true)
    void onMessage(String msg) {}
}
// after
@WebSocketClient(path = "/client")
class MyClient {
    @OnTextMessage
    void onMessage(String msg) {}
}
Defensive patterns

Strategy: validation

Validate before calling

// build-time: avoid broadcast on client endpoints
void checkCallback(WebSocketClient client) {
    for (Method m : client.getClass().getDeclaredMethods()) {
        if (m.isAnnotationPresent(OnTextMessage.class)
                && m.getAnnotation(OnTextMessage.class).broadcast()) {
            throw new IllegalStateException("broadcast not allowed on client: " + m);
        }
    }
}

Prevention

When it happens

Trigger: Declaring a client endpoint callback such as @OnTextMessage(broadcast = true) or @OnBinaryMessage(broadcast = true), or injecting a BroadcastSender into a client endpoint callback; the WebSocketProcessor detects callback.broadcast() while Target.CLIENT during annotation processing.

Common situations: Copying a @WebSocket endpoint class into a @WebSocketClient class without removing broadcast attributes; misunderstanding that client endpoints only have one peer so broadcast is meaningless.

Related errors


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