{"record":{"id":"eca0a8b8a736b7c4","repo":"alibaba/spring-cloud-alibaba","slug":"redisdatasource-sentinel-model-masterid-can-not-b","errorCode":null,"errorMessage":"RedisDataSource  sentinel model，masterId can not be empty","messagePattern":"RedisDataSource  sentinel model，masterId can not be empty","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/RedisDataSourceProperties.java","lineNumber":98,"sourceCode":"\t * redis sentinel model.\n\t */\n\tprivate @Nullable String masterId;\n\n\t@Override\n\tpublic void preCheck(String dataSourceName) {\n\t\tsuper.preCheck(dataSourceName);\n\t\tif (StringUtils.isEmpty(ruleKey)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"RedisDataSource  ruleKey can not be empty\");\n\t\t}\n\n\t\tif (StringUtils.isEmpty(channel)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"RedisDataSource  channel can not be empty\");\n\t\t}\n\n\t\tif (StringUtils.isEmpty(masterId)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"RedisDataSource  sentinel model，masterId can not be empty\");\n\t\t}\n\t}\n\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;","sourceCodeStart":80,"sourceCodeEnd":116,"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/config/RedisDataSourceProperties.java#L80-L116","documentation":"Thrown by RedisDataSourceProperties.preCheck when the masterId field is null or empty. The message references 'sentinel model' (note the full-width Chinese comma U+FF0C in the original source instead of ASCII comma). IMPORTANT GOTCHA: this check is UNCONDITIONAL — it always fires even when using standalone Redis (nodes not configured), not just in Redis Sentinel mode. The masterId is only actually used by the FactoryBean in the sentinel branch (when nodes is non-empty), but preCheck requires it regardless. This means standalone Redis users must also provide a masterId value even though it is unused.","triggerScenarios":"Configuring ANY Sentinel datasource of type 'redis' (standalone or sentinel) without masterId set. Since the check at line 97 has no guard on whether nodes are configured, it fires for both standalone and sentinel deployments. The masterId field is @Nullable with no default.","commonSituations":"1) Standalone Redis deployment (no sentinel nodes) — developer omits masterId thinking it is sentinel-only, but the unconditional check fires. 2) Redis Sentinel deployment where masterId was not provided. 3) Copy-paste from documentation that did not emphasize masterId as required for all Redis datasource configurations.","solutions":["Add spring.cloud.sentinel.datasource.<name>.redis.masterId=<any-value> to your configuration — even for standalone Redis, a non-empty value satisfies the check (the value is unused by the FactoryBean in standalone mode).","If using Redis Sentinel mode, set masterId to the actual Sentinel master identifier (e.g., mymaster).","Be aware this is a known design quirk: the check does not distinguish standalone from sentinel mode."],"exampleFix":"# before (broken — masterId missing in standalone Redis)\nspring:\n  cloud:\n    sentinel:\n      datasource:\n        ds1:\n          redis:\n            host: redis.local\n            ruleKey: sentinel:flow-rules\n            channel: sentinel-rule-updates\n\n# after (fixed — provide masterId even for standalone)\nspring:\n  cloud:\n    sentinel:\n      datasource:\n        ds1:\n          redis:\n            host: redis.local\n            ruleKey: sentinel:flow-rules\n            channel: sentinel-rule-updates\n            masterId: mymaster  # required by preCheck even in standalone mode","handlingStrategy":"validation","validationCode":"// IMPORTANT: masterId is required even for standalone Redis due to\n// the unconditional check in RedisDataSourceProperties.preCheck()\nString masterId = props.getRedis().getMasterId();\nif (!StringUtils.hasText(masterId)) {\n    // For standalone Redis, any non-empty value satisfies the check\n    log.warn(\"RedisDataSource masterId is empty — setting placeholder for standalone mode\");\n    props.getRedis().setMasterId(\"standalone-placeholder\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Be aware that masterId is unconditionally required by preCheck — even for standalone (non-sentinel) Redis.","For standalone Redis, set masterId to any non-empty placeholder value (it is unused by the FactoryBean).","For Redis Sentinel mode, set masterId to the actual sentinel master name (e.g., mymaster).","Document this gotcha in your project's deployment guide to save future debugging time."],"tags":["sentinel","redis","datasource","configuration","validation","sentinel-mode","gotcha"],"backgroundTag":null,"analyzedSha":"115d5901102009492e05d5ec18c3f79cad4077d0","analyzedAt":"2026-08-14T04:47:13.900Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}