{"record":{"id":"088330efd9d6203d","repo":"quarkusio/quarkus","slug":"onpongmessage-callback-must-return-void-or-uni-vo","errorCode":null,"errorMessage":"@OnPongMessage callback must return void or Uni<Void>: ","messagePattern":"@OnPongMessage 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":1109,"sourceCode":"        }\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            }\n        } else {\n            if (!callback.isReturnTypeVoid() && !isUniVoid(callback.returnType())) {\n                throw new WebSocketServerException(\n                        \"@OnPongMessage 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                    \"@OnPongMessage callback must accept exactly one message parameter of type io.vertx.core.buffer.Buffer: \"\n                            + callback.asString());\n        }\n    }\n\n    private void validateOnClose(Callback callback) {\n        if (KotlinUtils.isKotlinMethod(callback.method)) {\n            if (!callback.isReturnTypeVoid() && !isUniVoid(callback.returnType())\n                    && !callback.isKotlinSuspendFunctionReturningUnit()) {\n                throw new WebSocketServerException(\n                        \"@OnClose callback must return Unit or Uni<Void>: \" + callback.asString());\n            }","sourceCodeStart":1091,"sourceCodeEnd":1127,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java#L1091-L1127","documentation":"Quarkus websockets-next validates at build time that a method annotated with @OnPongMessage returns either void or Uni<Void> (or Unit for Kotlin suspend functions). A pong callback must not produce a value, since pong handling has no result to deliver back to the caller. The build fails with WebSocketServerException naming the offending callback via asString().","triggerScenarios":"Annotating a method with @OnPongMessage whose return type is something other than void or Uni<Void> (non-Kotlin), e.g. returning String, boolean, Response, or Uni<String>.","commonSituations":"Developer copies an @OnTextMessage callback signature (which may return values) and renames the annotation to @OnPongMessage; returning a status flag from pong handling; IDE-generated stubs returning a value.","solutions":["Change the @OnPongMessage method return type to void","If async handling is needed, return Uni<Void> (Mutiny) and ensure all paths resolve with null","For Kotlin suspend functions, return Unit (suspend function returning Unit is accepted)","Move any value-producing logic into a separate method and keep the callback side-effect only"],"exampleFix":"// before\n@OnPongMessage\nString onPong(Buffer data) { return data.toString(); }\n\n// after\n@OnPongMessage\nvoid onPong(Buffer data) { log.debug(\"pong: \" + data); }","handlingStrategy":"validation","validationCode":"// Check before annotating: all @OnPongMessage methods return void or Uni<Void>\nfor (Method m : MyWebSocket.class.getDeclaredMethods()) {\n    if (m.isAnnotationPresent(OnPongMessage.class)) {\n        boolean ok = m.getReturnType().equals(void.class)\n            || UniVoidChecker.isUniVoid(m.getGenericReturnType());\n        if (!ok) throw new IllegalStateException(m + \" must return void or Uni<Void>\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always declare @OnPongMessage as void unless async (Uni<Void>)","Never reuse @OnTextMessage signatures for pong callbacks","Let the Quarkus dev-mode build catch it early before packaging"],"tags":["quarkus","websockets-next","build-time-validation","callback-signature"],"backgroundTag":"callback-return-type-mismatch","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"}