quarkusio/quarkus · error · WebSocketServerException
Multiple client endpoints [%s, %s] define the same endpoint
Error message
Multiple client endpoints [%s, %s] define the same endpoint id: %s
What it means
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.
Source
Thrown at extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java:394
inboundProcessingMode = webSocketAnnotation.value("inboundProcessingMode");
} else {
target = Target.CLIENT;
path = getPath(webSocketClientAnnotation.value("path").asString());
DotName prevPath = clientPathToEndpoint.put(path, beanClass.name());
if (prevPath != null) {
throw new WebSocketServerException(
String.format("Multiple client endpoints [%s, %s] define the same path: %s", prevPath, beanClass,
path));
}
AnnotationValue clientIdValue = webSocketClientAnnotation.value("clientId");
if (clientIdValue == null) {
id = beanClass.name().toString();
} else {
id = clientIdValue.asString();
}
DotName prevId = clientIdToEndpoint.put(id, beanClass.name());
if (prevId != null) {
throw new WebSocketServerException(
String.format("Multiple client endpoints [%s, %s] define the same endpoint id: %s", prevId,
beanClass,
id));
}
inboundProcessingMode = webSocketClientAnnotation.value("inboundProcessingMode");
}
Callback onOpen = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_OPEN, callbackArguments, transformedAnnotations, path);
Callback onTextMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_TEXT_MESSAGE, callbackArguments, transformedAnnotations, path);
Callback onBinaryMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_BINARY_MESSAGE, callbackArguments, transformedAnnotations, path);
Callback onPingMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_PING_MESSAGE, callbackArguments, transformedAnnotations, path,
this::validateOnPingMessage);
Callback onPongMessage = findCallback(target, beanArchiveIndex.getIndex(), bean, beanClass,
WebSocketDotNames.ON_PONG_MESSAGE, callbackArguments, transformedAnnotations, path,View on GitHub (pinned to e1c734241f)
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
Example fix
// before
@WebSocketClient(path="/a", clientId="client") class C1 {}
@WebSocketClient(path="/b", clientId="client") class C2 {}
// after
@WebSocketClient(path="/b", clientId="client2") class C2 {} Defensive patterns
Strategy: validation
Validate before calling
@Test
void clientIdsUnique() {
Set<String> ids = new HashSet<>();
for (Class<?> c : allClients) {
WebSocketClient cl = c.getAnnotation(WebSocketClient.class);
String id = cl.clientId().isEmpty() ? c.getName() : cl.clientId();
if (!ids.add(id)) throw new AssertionError("Duplicate clientId: " + id);
}
} Prevention
- 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
When it happens
Trigger: Two @WebSocketClient classes declaring the same clientId value, or an explicit clientId matching another client endpoint class's implicit id.
Common situations: Copy-paste of client classes retaining clientId; renaming classes so defaults collide after explicit ids were normalized; generated clients sharing a template id.
Related errors
- Multiple endpoints [%s, %s] define the same endpoint id: %s
- Multiple global @OnError callbacks may not accept the same e
- Multiple client endpoints [%s, %s] define the same path: %s
- Multiple checked templates exist for the template path %s:
- Only a single instance of '${annotation}' is allowed per RES
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/da858a8963741ab7.
Report an issue: GitHub.