{"record":{"id":"8b50a9b1f87daf69","repo":"alibaba/spring-cloud-alibaba","slug":"serveraddr-and-path-must-not-be-null","errorCode":null,"errorMessage":"serverAddr and path must not be null","messagePattern":"serverAddr and path must not be null","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java","lineNumber":56,"sourceCode":"\tprivate @Nullable String groupId;\n\n\tprivate @Nullable String dataId;\n\n\tprivate @Nullable Converter converter;\n\n\t@Override\n\tpublic ZookeeperDataSource getObject() throws Exception {\n\t\tif (StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(dataId)) {\n\t\t\t// the path will be /{groupId}/{dataId}\n\t\t\tif (serverAddr == null || groupId == null || dataId == null) {\n\t\t\t\tthrow new IllegalStateException(\"serverAddr, groupId, and dataId must not be null\");\n\t\t\t}\n\t\t\treturn new ZookeeperDataSource(serverAddr, groupId, dataId, converter);\n\t\t}\n\t\telse {\n\t\t\t// using path directly\n\t\t\tif (serverAddr == null || path == null) {\n\t\t\t\tthrow new IllegalStateException(\"serverAddr and path must not be null\");\n\t\t\t}\n\t\t\treturn new ZookeeperDataSource(serverAddr, path, converter);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Class<?> getObjectType() {\n\t\treturn ZookeeperDataSource.class;\n\t}\n\n\tpublic @Nullable String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n\tpublic void setServerAddr(@Nullable String serverAddr) {\n\t\tthis.serverAddr = serverAddr;\n\t}\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/alibaba/spring-cloud-alibaba/blob/115d5901102009492e05d5ec18c3f79cad4077d0/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java#L38-L74","documentation":"Thrown by ZookeeperDataSourceFactoryBean.getObject() in the else branch (path mode) when serverAddr or path is null. The else branch is entered when either groupId or dataId is empty/not-provided, indicating the caller wants to use a raw Zookeeper path instead of groupId/dataId composition. In this mode, both serverAddr and path are required — if either is null, the IllegalStateException fires.","triggerScenarios":"Configuring a Sentinel datasource of type 'zk' where groupId or dataId is omitted (entering path mode) but either serverAddr or path is also missing. Common when a developer provides only groupId without dataId (falling to path mode unintentionally) and also forgets path.","commonSituations":"1) Developer provides zk.group-id but not zk.data-id (falls to path mode) and does not provide zk.path. 2) serverAddr is explicitly cleared while using path mode. 3) Programmatic FactoryBean with path set but serverAddr omitted, or vice versa. 4) Intended to use groupId/dataId mode but one was empty, silently switching to path mode without the required path.","solutions":["If using path mode, ensure both spring.cloud.sentinel.datasource.<name>.zk.server-addr and zk.path are set.","If you intended groupId/dataId mode, verify BOTH group-id and data-id are set — an empty value for either causes a silent switch to path mode.","Check for placeholder variables (${ZK_ADDR}, ${ZK_PATH}) that may resolve to null."],"exampleFix":"# before (broken — groupId without dataId falls to path mode, no path set)\nspring:\n  cloud:\n    sentinel:\n      datasource:\n        ds1:\n          zk:\n            server-addr: zk.local:2181\n            group-id: sentinel\n            # data-id omitted -> enters path mode, but path also missing\n\n# after (fixed — option A: complete groupId/dataId mode)\nspring:\n  cloud:\n    sentinel:\n      datasource:\n        ds1:\n          zk:\n            server-addr: zk.local:2181\n            group-id: sentinel\n            data-id: flow-rules\n\n# after (fixed — option B: use path mode explicitly)\nspring:\n  cloud:\n    sentinel:\n      datasource:\n        ds1:\n          zk:\n            server-addr: zk.local:2181\n            path: /sentinel/flow-rules","handlingStrategy":"validation","validationCode":"// Detect mode ambiguity before FactoryBean.getObject()\n// If using path mode, both serverAddr and path must be set\nboolean groupIdMode = StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(dataId);\nif (!groupIdMode) {\n    // Path mode\n    if (serverAddr == null) {\n        throw new IllegalStateException(\n            \"serverAddr required for ZK path mode (groupId/dataId not both set)\");\n    }\n    if (path == null) {\n        throw new IllegalStateException(\n            \"path required for ZK path mode — or set BOTH groupId and dataId for groupId/dataId mode\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When configuring ZK datasources, decide explicitly between groupId/dataId mode and path mode — set all relevant properties for the chosen mode.","If providing groupId, always also provide dataId to avoid unintentionally entering path mode.","Add a configuration validation test that checks ZK datasource mode consistency.","Document which mode each ZK datasource uses in your deployment guide."],"tags":["sentinel","zookeeper","datasource","factory-bean","configuration","validation"],"backgroundTag":null,"analyzedSha":"115d5901102009492e05d5ec18c3f79cad4077d0","analyzedAt":"2026-08-14T04:47:13.900Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}