{"record":{"id":"6bdc4f70ec581254","repo":"apache/shenyu","slug":"websocket-on-client-open-failed-namespaceid-is-null","errorCode":null,"errorMessage":"websocket on client open failed, namespaceId is null","messagePattern":"websocket on client open failed, namespaceId is null","errorType":"exception","errorClass":"ShenyuException","httpStatus":null,"severity":"error","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/websocket/WebsocketCollector.java","lineNumber":89,"sourceCode":"    private static final Map<Session, SessionSendQueue> SESSION_SEND_QUEUES = Maps.newConcurrentMap();\n    \n    private static final String SESSION_KEY = \"sessionKey\";\n    \n    /**\n     * On open.\n     *\n     * @param session the session\n     */\n    @OnOpen\n    public void onOpen(final Session session) {\n        String clientIp = getClientIp(session);\n        LOG.info(\"websocket on client[{}] open successful, maxTextMessageBufferSize: {}\",\n                clientIp, session.getMaxTextMessageBufferSize());\n        SESSION_SET.add(session);\n        \n        String namespaceId = getNamespaceId(session);\n        if (StringUtils.isBlank(namespaceId)) {\n            throw new ShenyuException(\"websocket on client open failed, namespaceId is null\");\n        }\n        LOG.info(\"websocket on client[{}] open successful, namespaceId: {}\", clientIp, namespaceId);\n        NAMESPACE_SESSION_MAP.computeIfAbsent(namespaceId, k -> Sets.newConcurrentHashSet()).add(session);\n    }\n    \n    private static String getClientIp(final Session session) {\n        if (!session.isOpen()) {\n            return StringUtils.EMPTY;\n        }\n        Map<String, Object> userProperties = session.getUserProperties();\n        if (MapUtils.isEmpty(userProperties)) {\n            return StringUtils.EMPTY;\n        }\n        \n        return Optional.ofNullable(userProperties.get(WebsocketListener.CLIENT_IP_NAME))\n                .map(Object::toString)\n                .orElse(StringUtils.EMPTY);\n    }","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/websocket/WebsocketCollector.java#L71-L107","documentation":"WebsocketCollector.onOpen registers a gateway websocket session into a per-namespace session map. The namespaceId is read from the session's request parameters; if it is missing or blank the connection cannot be attributed to a namespace, so onOpen throws ShenyuException, causing the websocket handshake/handler to fail for that client.","triggerScenarios":"A gateway opens the admin websocket sync connection (/websocket) without providing a `namespaceId` parameter (e.g. ws://admin:9095/websocket without ?namespaceId=...), or with an empty/blank namespaceId.","commonSituations":"Older gateway clients predating multi-namespace support connecting to a namespace-aware admin; hand-written websocket clients omitting the query parameter; reverse proxy stripping query strings from the upgrade request.","solutions":["Configure the gateway's shenyu.websocket sync url to include the namespaceId query parameter, e.g. ws://admin:9095/websocket?namespaceId=649330b6-v2.","Check shenyu.sync.websocket properties on the gateway side and admin's namespace config so both agree on the namespace id.","Upgrade the gateway to a version matching the admin's namespace support.","Verify any reverse proxy in front of admin preserves the query string on websocket upgrade requests."],"exampleFix":"// before (application.yml, gateway)\nshenyu:\n  sync:\n    websocket:\n      url: ws://admin:9095/websocket\n// after\nshenyu:\n  sync:\n    websocket:\n      url: ws://admin:9095/websocket?namespaceId=649330b6-v2","handlingStrategy":"validation","validationCode":"URI uri = URI.create(syncUrl);\nMap<String,String> q = parseQuery(uri.getRawQuery());\nif (q.get(\"namespaceId\") == null || q.get(\"namespaceId\").isBlank()) throw new IllegalStateException(\"websocket sync url missing namespaceId\");","typeGuard":null,"tryCatchPattern":"try {\n    session = container.connectToServer(...);\n} catch (DeploymentException e) {\n    LOG.error(\"websocket open failed — check namespaceId query param on the sync url\", e);\n}","preventionTips":["Always append ?namespaceId=<id> to the gateway's websocket sync url","Match the namespace id against the admin's namespace configuration","Keep reverse proxies from rewriting the upgrade URL query"],"tags":["websocket","data-sync","namespace","configuration"],"backgroundTag":"missing-required-argument","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}