apache/shenyu · error · ShenyuException
namespaceId can not be null
Error message
namespaceId can not be null
What it means
WebsocketCollector.send pushes a config-change message to all websocket sessions registered for the given namespaceId. A blank namespaceId means the message cannot be routed to any namespace's session set, so send throws ShenyuException. This is a server-side programming/config guard inside shenyu-admin's websocket sync publisher.
Solutions
- Fix the caller to pass the correct namespaceId, e.g. the namespace of the changed data record.
- Backfill NULL/blank namespace columns in the admin database (plugin/selector/rule tables) with the default namespace id.
- If a custom extension calls send(), derive namespaceId from the event's namespace instead of hard-coding null.
- Upgrade both admin and gateway to matching versions so namespace propagation is consistent.
Example fix
// before WebsocketCollector.send(null, JsonUtils.toJson(data), type); // after WebsocketCollector.send(data.getNamespaceId(), JsonUtils.toJson(data), type);
Defensive patterns
Strategy: validation
Validate before calling
if (namespaceId == null || namespaceId.isBlank()) {
throw new IllegalArgumentException("cannot push config: namespaceId is blank for " + data.getClass().getSimpleName());
} Try / catch
try {
WebsocketCollector.send(namespaceId, message, type);
} catch (ShenyuException e) {
LOG.error("websocket push skipped: {}", e.getMessage());
} Prevention
- Backfill namespace columns on all admin config tables
- Derive namespaceId from the data/event, never pass literals or null
- Run a startup check that config rows have non-null namespace
When it happens
Trigger: Any admin code path (config change listener, data-changed publisher) invokes WebsocketCollector.send with a null/blank namespaceId — typically when the event or data being pushed was created without a namespace (e.g. rows written before multi-namespace support, or a custom listener that doesn't set namespaceId).
Common situations: Admin DB rows (plugin/selector/rule data) with NULL namespace column; custom plugin/listener extensions calling send() directly without namespace; data migration from a pre-namespace ShenYu version.
Related errors
- websocket on client open failed, namespaceId is null
- namespace is not exist
- namespaceId is null
- namespace is not exist
- dynamic: result.getMessage() from…
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/b4e7093cc4b4be22.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/websocket/WebsocketCollector.java:276
} else {
SESSION_SET.forEach(session -> sendMessageBySession(session, message));
}
}
/**
* Send.
*
* @param namespaceId the namespaceId
* @param message the message
* @param type the type
*/
public static void send(final String namespaceId, final String message, final DataEventTypeEnum type) {
if (StringUtils.isBlank(message)) {
return;
}
if (StringUtils.isBlank(namespaceId)) {
throw new ShenyuException("namespaceId can not be null");
}
LOG.info("websocket send message to namespaceId: {}, message: {}", namespaceId, maskSensitive(message));
if (DataEventTypeEnum.MYSELF == type) {
Session session = (Session) ThreadLocalUtils.get(SESSION_KEY);
if (Objects.nonNull(session)) {
if (session.isOpen()) {
sendMessageBySession(session, message);
} else {
NAMESPACE_SESSION_MAP.getOrDefault(namespaceId, Sets.newConcurrentHashSet()).remove(session);
removeSessionSendQueue(session);
}
}
} else {
NAMESPACE_SESSION_MAP.getOrDefault(namespaceId, Sets.newConcurrentHashSet())
.forEach(session -> sendMessageBySession(session, message));
}
}View on GitHub (pinned to 567142e072)