{"record":{"id":"7cc70465fb7dbca1","repo":"quarkusio/quarkus","slug":"s-callback-declared-on-a-client-endpoint-must-no","errorCode":null,"errorMessage":"@%s callback declared on a client endpoint must not broadcast messages: %s","messagePattern":"@(.+?) callback declared on a client endpoint must not broadcast messages: (.+?)","errorType":"validation","errorClass":"WebSocketClientException","httpStatus":null,"severity":"error","filePath":"extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java","lineNumber":1924,"sourceCode":"            if (callback.acceptsMessage()) {\n                if (messageArguments > 1) {\n                    throw new WebSocketException(\n                            String.format(\"@%s callback may accept at most 1 message parameter; found %s: %s\",\n                                    DotNames.simpleName(callback.annotation.name()),\n                                    messageArguments,\n                                    callback.asString()));\n                }\n            } else {\n                if (messageArguments != 0) {\n                    throw new WebSocketException(\n                            String.format(\"@%s callback must not accept a message parameter; found %s: %s\",\n                                    DotNames.simpleName(callback.annotation.name()),\n                                    messageArguments,\n                                    callback.asString()));\n                }\n            }\n            if (target == Target.CLIENT && callback.broadcast()) {\n                throw new WebSocketClientException(\n                        String.format(\"@%s callback declared on a client endpoint must not broadcast messages: %s\",\n                                DotNames.simpleName(callback.annotation.name()),\n                                callback.asString()));\n            }\n            if (validator != null) {\n                validator.accept(callback);\n            }\n            return callback;\n        }\n        throw new WebSocketException(\n                String.format(\"There can be only one callback annotated with %s declared on %s\", annotationName, beanClass));\n    }\n\n    private static ExecutionModel executionModel(MethodInfo method, TransformedAnnotationsBuildItem transformedAnnotations) {\n        if (KotlinUtils.isKotlinSuspendMethod(method)\n                && (transformedAnnotations.hasAnnotation(method, WebSocketDotNames.RUN_ON_VIRTUAL_THREAD)\n                        || transformedAnnotations.hasAnnotation(method.declaringClass(),\n                                WebSocketDotNames.RUN_ON_VIRTUAL_THREAD)","sourceCodeStart":1906,"sourceCodeEnd":1942,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java#L1906-L1942","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove broadcast = true (and any BroadcastSender parameter) from callbacks on the client endpoint class","Use OnTextMessage/OnBinaryMessage without broadcast on the client, processing the single inbound message directly","If fan-out to multiple server sessions is needed, that logic belongs on the server endpoint, not the client"],"exampleFix":"// before\n@WebSocketClient(path = \"/client\")\nclass MyClient {\n    @OnTextMessage(broadcast = true)\n    void onMessage(String msg) {}\n}\n// after\n@WebSocketClient(path = \"/client\")\nclass MyClient {\n    @OnTextMessage\n    void onMessage(String msg) {}\n}","handlingStrategy":"validation","validationCode":"// build-time: avoid broadcast on client endpoints\nvoid checkCallback(WebSocketClient client) {\n    for (Method m : client.getClass().getDeclaredMethods()) {\n        if (m.isAnnotationPresent(OnTextMessage.class)\n                && m.getAnnotation(OnTextMessage.class).broadcast()) {\n            throw new IllegalStateException(\"broadcast not allowed on client: \" + m);\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never set broadcast = true in @WebSocketClient endpoint callbacks","Avoid injecting BroadcastSender into client endpoint methods"],"tags":["websockets","build-time-validation","client-endpoint"],"backgroundTag":"websocket-client-broadcast-not-allowed","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}