{"record":{"id":"728394959a75fc04","repo":"quarkusio/quarkus","slug":"endpoint-class-may-not-be-annotated-with-both-web","errorCode":null,"errorMessage":"Endpoint class may not be annotated with both @WebSocket and @WebSocketClient: ","messagePattern":"Endpoint class may not be annotated with both @WebSocket and @WebSocketClient: ","errorType":"validation","errorClass":"WebSocketException","httpStatus":null,"severity":"error","filePath":"extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java","lineNumber":344,"sourceCode":"            BuildProducer<WebSocketEndpointBuildItem> endpoints) {\n\n        IndexView index = beanArchiveIndex.getIndex();\n\n        // Collect WebSocket endpoints\n        Map<String, DotName> serverIdToEndpoint = new HashMap<>();\n        Map<String, DotName> serverPathToEndpoint = new HashMap<>();\n        Map<String, DotName> clientIdToEndpoint = new HashMap<>();\n        Map<String, DotName> clientPathToEndpoint = new HashMap<>();\n\n        for (BeanInfo bean : beanDiscoveryFinished.beanStream().classBeans()) {\n            ClassInfo beanClass = bean.getTarget().get().asClass();\n            AnnotationInstance webSocketAnnotation = beanClass.annotation(WebSocketDotNames.WEB_SOCKET);\n            AnnotationInstance webSocketClientAnnotation = beanClass.annotation(WebSocketDotNames.WEB_SOCKET_CLIENT);\n\n            if (webSocketAnnotation == null && webSocketClientAnnotation == null) {\n                continue;\n            } else if (webSocketAnnotation != null && webSocketClientAnnotation != null) {\n                throw new WebSocketException(\n                        \"Endpoint class may not be annotated with both @WebSocket and @WebSocketClient: \" + beanClass);\n            }\n            String path;\n            String id;\n            AnnotationValue inboundProcessingMode;\n            Target target;\n\n            if (webSocketAnnotation != null) {\n                target = Target.SERVER;\n                path = getPath(webSocketAnnotation.value(\"path\").asString());\n                if (beanClass.nestingType() == NestingType.INNER) {\n                    // Sub-websocket - merge the path from the enclosing classes\n                    path = mergePath(getPathPrefix(index, beanClass.enclosingClass()), path);\n                }\n                DotName prevPath = serverPathToEndpoint.put(path, beanClass.name());\n                if (prevPath != null) {\n                    throw new WebSocketServerException(\n                            String.format(\"Multiple endpoints [%s, %s] define the same path: %s\", prevPath, beanClass, path));","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java#L326-L362","documentation":"A bean class annotated with @WebSocket is a server endpoint and with @WebSocketClient is a client endpoint; these are mutually exclusive. Quarkus rejects the deployment when both annotations are present because the endpoint's target (server vs client), path registration and lifecycle cannot be determined.","triggerScenarios":"Annotating the same class with both @WebSocket and @WebSocketClient, e.g. when sharing one class between a server and client test, or copy-pasting a client class and adding @WebSocket on top.","commonSituations":"Code sharing between server and client modules; accidental import of the wrong annotation causing a double annotation; refactoring an endpoint into a client and leaving the old annotation behind.","solutions":["Remove either @WebSocket or @WebSocketClient from the class, keeping the one that matches its role","Split the shared logic into two classes, one per annotation","Check imports — io.quarkus.websockets.next.WebSocket vs WebSocketClient"],"exampleFix":"// before\n@WebSocket(path = \"/ws\")\n@WebSocketClient(path = \"/client\")\nclass MyWs {}\n// after\n@WebSocket(path = \"/ws\")\nclass MyWs {}","handlingStrategy":"validation","validationCode":"// Compile-time-ish check in a shared base or unit test\nvoid assertSingleWsAnnotation(Class<?> c) {\n  boolean server = c.isAnnotationPresent(WebSocket.class);\n  boolean client = c.isAnnotationPresent(WebSocketClient.class);\n  if (server && client) throw new IllegalStateException(c + \" has both @WebSocket and @WebSocketClient\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Decide server vs client role per class; never share one annotated class for both","Double-check imports when copy-pasting between server and client packages","Split shared logic into a plain superclass consumed by two role-specific subclasses"],"tags":["websocket","build-time","annotation","quarkus"],"backgroundTag":"conflicting-annotations","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"}