{"record":{"id":"fade16544820c78a","repo":"quarkusio/quarkus","slug":"onpingmessage-callback-must-return-unit-or-uni-vo","errorCode":null,"errorMessage":"@OnPingMessage callback must return Unit or Uni<Void>: ","messagePattern":"@OnPingMessage callback must return Unit 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":1083,"sourceCode":"            throw new WebSocketServerException(\"Enclosing class not found in index: \" + enclosingClass);\n        }\n        AnnotationInstance webSocketAnnotation = enclosingClass.annotation(WebSocketDotNames.WEB_SOCKET);\n        if (webSocketAnnotation != null) {\n            String path = getPath(webSocketAnnotation.value(\"path\").asString());\n            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)) {","sourceCodeStart":1065,"sourceCodeEnd":1101,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java#L1065-L1101","documentation":"An @OnPingMessage callback in Kotlin must return Unit, Uni<Void>, or be a suspend function returning Unit. Any other return type is rejected at build time so ping handling stays fire-and-forget or reactive-void. The message includes the offending callback's string form.","triggerScenarios":"A Kotlin method annotated @OnPingMessage returns a non-Unit, non-Uni<Void> type (e.g. String, Int, Uni<String>) and is neither plain void nor a suspend function returning Unit.","commonSituations":"Returning the pong/echo value from the ping handler; forgetting that Kotlin Unit maps through suspend wrappers; copying Java signatures into Kotlin without adjusting the return type.","solutions":["Change the callback return type to Unit (or make it suspend returning Unit).","Alternatively return io.smallrye.mutiny.Uni<Void>.","Return the computed value via a different mechanism (e.g. send a message from within the handler) instead of returning it from the ping callback."],"exampleFix":"// before\n@OnPingMessage\nfun onPing(buffer: Buffer): String { return \"pong\" }\n\n// after\n@OnPingMessage\nfun onPing(buffer: Buffer) { /* handle */ }","handlingStrategy":"validation","validationCode":"// Kotlin pre-check: @OnPingMessage must return Unit/Uni<Void> or suspend Unit\nfun checkPingCallback(m: KFunction<*>) {\n    val ret = m.returnType.classifier\n    check(ret == Unit::class || ret == Uni::class)\n        { \"@OnPingMessage must return Unit or Uni<Void>: ${m.name}\" }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare ping/pong handlers without an explicit return type in Kotlin","Use suspend only when needed; Unit return is simplest","Do not return echo values from ping callbacks","Lint for callback signatures in CI"],"tags":["quarkus","websockets-next","kotlin","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-14T00:17:10.932Z"}