apache/shenyu · error · ShenyuException
Class missing annotation ShenyuServerEndpoint! class name:
Error message
Class missing annotation ShenyuServerEndpoint! class name:
What it means
ShenyuServerEndpointerExporter.registerEndpoint() requires each candidate class to be annotated with @ShenyuServerEndpoint. When AnnotatedElementUtils.findMergedAnnotation returns null, the class cannot be converted into a websocket ServerEndpointConfig for gateway registration, so a ShenyuException naming the offending class is thrown.
Solutions
- Annotate the websocket endpoint class with @ShenyuServerEndpoint("/your/path") in addition to @ServerEndpoint.
- Check the exception's 'class name:' suffix to find the offending class and confirm it is the intended endpoint.
- Narrow the scanned base packages so unrelated beans are not passed to registerEndpoint.
- If the class is intentionally not an endpoint, remove it from the beans passed to the exporter.
Example fix
// before
@ServerEndpoint("/websocket/echo")
public class EchoServer { ... }
// after
@ServerEndpoint("/websocket/echo")
@ShenyuServerEndpoint("/websocket/echo")
public class EchoServer { ... } Defensive patterns
Strategy: validation
Validate before calling
Class<?> pojo = ...;
if (AnnotatedElementUtils.findMergedAnnotation(pojo, ShenyuServerEndpoint.class) == null) {
throw new IllegalArgumentException(pojo.getName() + " must be annotated with @ShenyuServerEndpoint");
} Type guard
boolean isShenyuEndpoint(Class<?> c) {
return AnnotatedElementUtils.findMergedAnnotation(c, ShenyuServerEndpoint.class) != null;
} Try / catch
try {
exporter.registerEndpoint(pojo);
} catch (ShenyuException e) {
LOG.error("Endpoint registration failed: {}", e.getMessage());
} Prevention
- Always pair @ServerEndpoint with @ShenyuServerEndpoint on gateway-exposed websocket handlers.
- Add an ArchUnit/reflection scan test asserting all scanned websocket beans carry the annotation.
- Limit component scanning base packages to classes that are actual endpoints.
When it happens
Trigger: registerEndpoint(pojo) is called (directly or via registerEndpointsBeans scanning) with a bean class that lacks the @ShenyuServerEndpoint annotation — e.g. a plain @ServerEndpoint JSR-356 class or an arbitrary bean picked up by the endpoint scan.
Common situations: Developers annotating websocket handlers only with javax/jakarta @ServerEndpoint and forgetting the ShenYu-specific @ShenyuServerEndpoint; passing non-endpoint helper beans into registerEndpoint; bean scanning picking up unrelated classes in the configured base packages.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- namespaceId is not exist
- websocket on client open failed, namespaceId is null
- namespaceId can not be null
- websocket sync token is not configured
- websocket sync token is invalid
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/438010483888ada5.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-client/shenyu-client-websocket/shenyu-client-spring-websocket/src/main/java/org/apache/shenyu/client/spring/websocket/init/ShenyuServerEndpointerExporter.java:79
protected void initServletContext(final ServletContext servletContext) {
if (Objects.isNull(this.serverContainer)) {
this.serverContainer = (ServerContainer) servletContext.getAttribute("jakarta.websocket.server.ServerContainer");
}
}
@Override
protected boolean isContextRequired() {
return false;
}
/**
* Register endpoint.
* @param pojo pojo
*/
public void registerEndpoint(final Class<?> pojo) {
ShenyuServerEndpoint annotation = AnnotatedElementUtils.findMergedAnnotation(pojo, ShenyuServerEndpoint.class);
if (Objects.isNull(annotation)) {
throw new ShenyuException("Class missing annotation ShenyuServerEndpoint! class name: " + pojo.getName());
}
String path = annotation.value();
Class<? extends ServerEndpointConfig.Configurator> configuratorClazz = annotation.configurator();
ServerEndpointConfig.Configurator configurator = null;
if (!configuratorClazz.equals(ServerEndpointConfig.Configurator.class)) {
try {
configurator = annotation.configurator().getConstructor().newInstance();
} catch (ReflectiveOperationException ex) {
LOG.error("ShenyuServerEndpoint configurator init fail! Class name: {}, configurator name: {}", pojo.getName(), annotation.configurator().getName());
throw new ShenyuException(ex);
}
}
ServerEndpointConfig sec = ServerEndpointConfig.Builder.create(pojo, path)
.decoders(Arrays.asList(annotation.decoders()))
.encoders(Arrays.asList(annotation.encoders()))
.subprotocols(Arrays.asList(annotation.subprotocols()))
.configurator(configurator).build();View on GitHub (pinned to 567142e072)