quarkusio/quarkus · error · WebSocketServerException

Multiple endpoints [%s, %s] define the same path: %s

Error message

Multiple endpoints [%s, %s] define the same path: %s

What it means

Quarkus websockets-next maps server endpoint paths to endpoint classes in a build-time registry; two @WebSocket endpoints resolving to the same path (after prefix merging for nested classes) make routing ambiguous, so WebSocketServerException is thrown.

Source

Thrown at extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java:361

            } else if (webSocketAnnotation != null && webSocketClientAnnotation != null) {
                throw new WebSocketException(
                        "Endpoint class may not be annotated with both @WebSocket and @WebSocketClient: " + beanClass);
            }
            String path;
            String id;
            AnnotationValue inboundProcessingMode;
            Target target;

            if (webSocketAnnotation != null) {
                target = Target.SERVER;
                path = getPath(webSocketAnnotation.value("path").asString());
                if (beanClass.nestingType() == NestingType.INNER) {
                    // Sub-websocket - merge the path from the enclosing classes
                    path = mergePath(getPathPrefix(index, beanClass.enclosingClass()), path);
                }
                DotName prevPath = serverPathToEndpoint.put(path, beanClass.name());
                if (prevPath != null) {
                    throw new WebSocketServerException(
                            String.format("Multiple endpoints [%s, %s] define the same path: %s", prevPath, beanClass, path));
                }
                AnnotationValue endpointIdValue = webSocketAnnotation.value("endpointId");
                if (endpointIdValue == null) {
                    id = beanClass.name().toString();
                } else {
                    id = endpointIdValue.asString();
                }
                DotName prevId = serverIdToEndpoint.put(id, beanClass.name());
                if (prevId != null) {
                    throw new WebSocketServerException(
                            String.format("Multiple endpoints [%s, %s] define the same endpoint id: %s", prevId, beanClass,
                                    id));
                }
                inboundProcessingMode = webSocketAnnotation.value("inboundProcessingMode");
            } else {
                target = Target.CLIENT;
                path = getPath(webSocketClientAnnotation.value("path").asString());

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change one endpoint's @WebSocket path so paths are unique
  2. Adjust the path prefix of the enclosing class for nested endpoints
  3. Use distinct path variables/segments to differentiate the endpoints

Example fix

// before
@WebSocket(path = "/ws/echo") class A {}
@WebSocket(path = "/ws/echo") class B {}
// after
@WebSocket(path = "/ws/echo") class A {}
@WebSocket(path = "/ws/echo2") class B {}
Defensive patterns

Strategy: validation

Validate before calling

// Unit test guarding path uniqueness across endpoints
@Test
void serverPathsUnique() {
  var paths = new HashSet<String>();
  for (Class<?> c : List.of(EchoSocket.class, ChatSocket.class)) {
    String p = c.getAnnotation(WebSocket.class).path();
    if (!paths.add(p)) throw new AssertionError("Duplicate server path: " + p);
  }
}

Prevention

When it happens

Trigger: Two @WebSocket classes with identical path values, or a nested (inner) endpoint whose merged path with its enclosing class prefix collides with another endpoint's path.

Common situations: Copy-pasting an endpoint and forgetting to change the path; two nested websockets that merge to the same prefix + path; dynamic path expressions evaluating to the same literal.

Related errors


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