{"record":{"id":"da858a8963741ab7","repo":"quarkusio/quarkus","slug":"multiple-client-endpoints-s-s-define-the-same-da858a","errorCode":null,"errorMessage":"Multiple client endpoints [%s, %s] define the same endpoint id: %s","messagePattern":"Multiple client endpoints \\[(.+?), (.+?)\\] define the same endpoint id: (.+?)","errorType":"validation","errorClass":"WebSocketServerException","httpStatus":null,"severity":"error","filePath":"extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java","lineNumber":394,"sourceCode":"                inboundProcessingMode = webSocketAnnotation.value(\"inboundProcessingMode\");\n            } else {\n                target = Target.CLIENT;\n                path = getPath(webSocketClientAnnotation.value(\"path\").asString());\n                DotName prevPath = clientPathToEndpoint.put(path, beanClass.name());\n                if (prevPath != null) {\n                    throw new WebSocketServerException(\n                            String.format(\"Multiple client endpoints [%s, %s] define the same path: %s\", prevPath, beanClass,\n                                    path));\n                }\n                AnnotationValue clientIdValue = webSocketClientAnnotation.value(\"clientId\");\n                if (clientIdValue == null) {\n                    id = beanClass.name().toString();\n                } else {\n                    id = clientIdValue.asString();\n                }\n                DotName prevId = clientIdToEndpoint.put(id, beanClass.name());\n                if (prevId != null) {\n                    throw new WebSocketServerException(\n                            String.format(\"Multiple client endpoints [%s, %s] define the same endpoint id: %s\", prevId,\n                                    beanClass,\n                                    id));\n                }\n                inboundProcessingMode = webSocketClientAnnotation.value(\"inboundProcessingMode\");\n            }\n\n            Callback onOpen = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,\n                    WebSocketDotNames.ON_OPEN, callbackArguments, transformedAnnotations, path);\n            Callback onTextMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,\n                    WebSocketDotNames.ON_TEXT_MESSAGE, callbackArguments, transformedAnnotations, path);\n            Callback onBinaryMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,\n                    WebSocketDotNames.ON_BINARY_MESSAGE, callbackArguments, transformedAnnotations, path);\n            Callback onPingMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,\n                    WebSocketDotNames.ON_PING_MESSAGE, callbackArguments, transformedAnnotations, path,\n                    this::validateOnPingMessage);\n            Callback onPongMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,\n                    WebSocketDotNames.ON_PONG_MESSAGE, callbackArguments, transformedAnnotations, path,","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java#L376-L412","documentation":"Client endpoints also require unique ids (from @WebSocketClient(clientId=...) or the class name by default). collectEndpoints detects a second client endpoint reusing an existing id and throws WebSocketServerException because client lookups by id would be ambiguous.","triggerScenarios":"Two @WebSocketClient classes declaring the same clientId value, or an explicit clientId matching another client endpoint class's implicit id.","commonSituations":"Copy-paste of client classes retaining clientId; renaming classes so defaults collide after explicit ids were normalized; generated clients sharing a template id.","solutions":["Change the clientId on one of the client endpoints","Remove the explicit clientId to fall back to the unique class-name id","Grep for the duplicated clientId to locate all usages, including in connection-open code"],"exampleFix":"// before\n@WebSocketClient(path=\"/a\", clientId=\"client\") class C1 {}\n@WebSocketClient(path=\"/b\", clientId=\"client\") class C2 {}\n// after\n@WebSocketClient(path=\"/b\", clientId=\"client2\") class C2 {}","handlingStrategy":"validation","validationCode":"@Test\nvoid clientIdsUnique() {\n  Set<String> ids = new HashSet<>();\n  for (Class<?> c : allClients) {\n    WebSocketClient cl = c.getAnnotation(WebSocketClient.class);\n    String id = cl.clientId().isEmpty() ? c.getName() : cl.clientId();\n    if (!ids.add(id)) throw new AssertionError(\"Duplicate clientId: \" + id);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer default (class-name) client ids; set clientId only when needed","Store client ids as constants shared with open-connection call sites","Grep for clientId strings after renaming clients"],"tags":["websocket","build-time","client","endpoint-id","duplicate"],"backgroundTag":"duplicate-endpoint-id","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"}