{"record":{"id":"88bcb164d5757ed4","repo":"quarkusio/quarkus","slug":"s-callback-must-not-accept-a-message-parameter","errorCode":null,"errorMessage":"@%s callback must not accept a message parameter; found %s: %s","messagePattern":"@(.+?) callback must not accept a message parameter; found (.+?): (.+?)","errorType":"validation","errorClass":"WebSocketException","httpStatus":null,"severity":"error","filePath":"extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java","lineNumber":1916,"sourceCode":"            return null;\n        } else if (annotations.size() == 1) {\n            AnnotationInstance annotation = annotations.get(0);\n            MethodInfo method = annotation.target().asMethod();\n            Callback callback = new Callback(target, annotation, bean, method,\n                    executionModel(method, transformedAnnotations), callbackArguments, transformedAnnotations,\n                    endpointPath, index);\n            long messageArguments = callback.arguments.stream().filter(ca -> ca instanceof MessageCallbackArgument).count();\n            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(","sourceCodeStart":1898,"sourceCodeEnd":1934,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java#L1898-L1934","documentation":"Callbacks that do not accept messages (acceptsMessage() is false, e.g. @OnOpen, @OnClose, @OnPongMessage per their rules) must not declare any message parameters. If one or more MessageCallbackArgument parameters are found, the build fails naming the annotation, the count, and the callback.","triggerScenarios":"Adding a message-typed parameter (String, Buffer, DTO) to an @OnOpen or @OnClose method; annotation not matched by acceptsMessage() due to its kind while its signature looks like a message handler.","commonSituations":"Developer expects to receive the last message in onOpen/onClose; copy-paste from an @OnTextMessage handler; leftover message parameter after changing the annotation.","solutions":["Remove the message parameter from the @OnOpen/@OnClose callback","Store the needed data in connection-scoped state (e.g. a request-scoped bean or WebSocketConnection attribute) instead","If message data is genuinely needed at that lifecycle point, use an appropriate @OnTextMessage/@OnBinaryMessage callback"],"exampleFix":"// before\n@OnOpen\nvoid onOpen(String firstMessage) {}\n\n// after\n@OnOpen\nvoid onOpen(WebSocketConnection conn) {}\n","handlingStrategy":"validation","validationCode":"for (Method m : MyWebSocket.class.getDeclaredMethods()) {\n    var a = m.getAnnotation(OnOpen.class);\n    if (a != null || m.isAnnotationPresent(OnClose.class)) {\n        boolean hasMessageParam = Arrays.stream(m.getParameterTypes())\n            .anyMatch(t -> t == String.class || t == byte[].class\n                || t.getName().equals(\"io.vertx.core.buffer.Buffer\"));\n        if (hasMessageParam) throw new IllegalStateException(m + \" must not accept a message parameter\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lifecycle callbacks (@OnOpen/@OnClose) take only connection/context parameters","Remove leftover message params when switching annotations","Carry state via connection-scoped beans, not callback arguments"],"tags":["quarkus","websockets-next","build-time-validation","callback-signature"],"backgroundTag":"callback-parameter-type-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}