{"record":{"id":"d2b09066ed543d85","repo":"quarkusio/quarkus","slug":"onpingmessage-callback-must-return-void-or-uni-vo","errorCode":null,"errorMessage":"@OnPingMessage callback must return void or Uni<Void>: ","messagePattern":"@OnPingMessage callback must return void or Uni<Void>: ","errorType":"validation","errorClass":"WebSocketServerException","httpStatus":null,"severity":"error","filePath":"extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java","lineNumber":1088,"sourceCode":"            if (enclosingClass.nestingType() == NestingType.INNER) {\n                return mergePath(getPathPrefix(index, enclosingClass.enclosingClass()), path);\n            } else {\n                return path.endsWith(\"/\") ? path.substring(path.length() - 1) : path;\n            }\n        }\n        return \"\";\n    }\n\n    private void validateOnPingMessage(Callback callback) {\n        if (KotlinUtils.isKotlinMethod(callback.method)) {\n            if (!callback.isReturnTypeVoid() && !isUniVoid(callback.returnType())\n                    && !callback.isKotlinSuspendFunctionReturningUnit()) {\n                throw new WebSocketServerException(\n                        \"@OnPingMessage callback must return Unit or Uni<Void>: \" + callback.asString());\n            }\n        } else {\n            if (!callback.isReturnTypeVoid() && !isUniVoid(callback.returnType())) {\n                throw new WebSocketServerException(\n                        \"@OnPingMessage callback must return void or Uni<Void>: \" + callback.asString());\n            }\n        }\n        Type messageType = callback.argumentType(MessageCallbackArgument::isMessage);\n        if (messageType == null || !messageType.name().equals(WebSocketDotNames.BUFFER)) {\n            throw new WebSocketServerException(\n                    \"@OnPingMessage callback must accept exactly one message parameter of type io.vertx.core.buffer.Buffer: \"\n                            + callback.asString());\n        }\n    }\n\n    private void validateOnPongMessage(Callback callback) {\n        if (KotlinUtils.isKotlinMethod(callback.method)) {\n            if (!callback.isReturnTypeVoid() && !isUniVoid(callback.returnType())\n                    && !callback.isKotlinSuspendFunctionReturningUnit()) {\n                throw new WebSocketServerException(\n                        \"@OnPongMessage callback must return Unit or Uni<Void>: \" + callback.asString());\n            }","sourceCodeStart":1070,"sourceCodeEnd":1106,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java#L1070-L1106","documentation":"Thrown by WebSocketProcessor.validateOnPingMessage when a Kotlin @OnPingMessage callback has an invalid return type: the callback is neither void, Uni<Void>, nor a Kotlin suspend function returning Unit. Ping callbacks only acknowledge the frame; any other return value has nowhere to go, so build-time validation aborts with the callback description appended to the message.","triggerScenarios":"A Java method annotated @OnPingMessage returns something other than void or Uni<Void> — e.g. String, Buffer, Uni<String>, CompletionStage<Void> written without Mutiny.","commonSituations":"Returning an echo/acknowledgement value from the ping handler; using java.util.concurrent.CompletionStage instead of Mutiny Uni; accidental return of intermediate computation results.","solutions":["Change the return type to void.","Or return io.smallrye.mutiny.Uni<Void> for reactive handling.","Move any result-producing logic into an explicit message send within the handler body.","If you need CompletionStage semantics, convert with Uni.createFrom().completionStage(...) and return Uni<Void>."],"exampleFix":"// before\n@OnPingMessage\nString onPing(Buffer buffer) { return \"pong\"; }\n\n// after\n@OnPingMessage\nvoid onPing(Buffer buffer) { /* handle */ }","handlingStrategy":"validation","validationCode":"// Java pre-check: @OnPingMessage must return void or Uni<Void>\nstatic void checkPingCallback(Method m) {\n    Class<?> r = m.getReturnType();\n    if (!(r == void.class || r == io.smallrye.mutiny.Uni.class))\n        throw new IllegalStateException(\"@OnPingMessage must return void or Uni<Void>: \" + m);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare @OnPingMessage methods void unless reactive Uni<Void> is needed","Use Mutiny Uni, not CompletionStage, for async handlers","Never return values from ping callbacks","Add an annotation-processing test over callback signatures"],"tags":["quarkus","websockets-next","java","callback","build-time"],"backgroundTag":"invalid-callback-return-type","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"}