{"record":{"id":"b4e7093cc4b4be22","repo":"apache/shenyu","slug":"namespaceid-can-not-be-null","errorCode":null,"errorMessage":"namespaceId can not be null","messagePattern":"namespaceId can not be null","errorType":"validation","errorClass":"ShenyuException","httpStatus":null,"severity":"error","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/websocket/WebsocketCollector.java","lineNumber":276,"sourceCode":"        } else {\n            SESSION_SET.forEach(session -> sendMessageBySession(session, message));\n        }\n        \n    }\n    \n    /**\n     * Send.\n     *\n     * @param namespaceId the namespaceId\n     * @param message the message\n     * @param type the type\n     */\n    public static void send(final String namespaceId, final String message, final DataEventTypeEnum type) {\n        if (StringUtils.isBlank(message)) {\n            return;\n        }\n        if (StringUtils.isBlank(namespaceId)) {\n            throw new ShenyuException(\"namespaceId can not be null\");\n        }\n        LOG.info(\"websocket send message to namespaceId: {}, message: {}\", namespaceId, maskSensitive(message));\n        if (DataEventTypeEnum.MYSELF == type) {\n            Session session = (Session) ThreadLocalUtils.get(SESSION_KEY);\n            if (Objects.nonNull(session)) {\n                if (session.isOpen()) {\n                    sendMessageBySession(session, message);\n                } else {\n                    NAMESPACE_SESSION_MAP.getOrDefault(namespaceId, Sets.newConcurrentHashSet()).remove(session);\n                    removeSessionSendQueue(session);\n                }\n            }\n        } else {\n            NAMESPACE_SESSION_MAP.getOrDefault(namespaceId, Sets.newConcurrentHashSet())\n                    .forEach(session -> sendMessageBySession(session, message));\n        }\n        \n    }","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/websocket/WebsocketCollector.java#L258-L294","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nWebsocketCollector.send(null, JsonUtils.toJson(data), type);\n// after\nWebsocketCollector.send(data.getNamespaceId(), JsonUtils.toJson(data), type);","handlingStrategy":"validation","validationCode":"if (namespaceId == null || namespaceId.isBlank()) {\n    throw new IllegalArgumentException(\"cannot push config: namespaceId is blank for \" + data.getClass().getSimpleName());\n}","typeGuard":null,"tryCatchPattern":"try {\n    WebsocketCollector.send(namespaceId, message, type);\n} catch (ShenyuException e) {\n    LOG.error(\"websocket push skipped: {}\", e.getMessage());\n}","preventionTips":["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"],"tags":["websocket","data-sync","namespace","null-argument"],"backgroundTag":"null-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"}