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

  1. Change the clientId on one of the client endpoints
  2. Remove the explicit clientId to fall back to the unique class-name id
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/da858a8963741ab7. Report an issue: GitHub.