{"record":{"id":"b7647b28555da193","repo":"redis/jedis","slug":"at-least-one-sentinel-must-be-specified-for-sentin","errorCode":null,"errorMessage":"At least one sentinel must be specified for Sentinel mode","messagePattern":"At least one sentinel must be specified for Sentinel mode","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/builders/SentinelClientBuilder.java","lineNumber":104,"sourceCode":"    return this;\n  }\n\n  @Override\n  protected ConnectionProvider createDefaultConnectionProvider() {\n    return new SentineledConnectionProvider(this.masterName, this.clientConfig, this.cache,\n        this.poolConfig, this.sentinels, this.sentinelClientConfig, sentinelReconnectDelay);\n  }\n\n  @Override\n  protected void validateSpecificConfiguration() {\n    validateCommonConfiguration();\n\n    if (masterName == null || masterName.trim().isEmpty()) {\n      throw new IllegalArgumentException(\"Master name is required for Sentinel mode\");\n    }\n\n    if (sentinels == null || sentinels.isEmpty()) {\n      throw new IllegalArgumentException(\n          \"At least one sentinel must be specified for Sentinel mode\");\n    }\n  }\n\n  @Override\n  public C build() {\n    if (sentinelClientConfig == null) {\n      // Sentinel connections use the legacy Jedis client which does not support RESP3\n      // auto-negotiation, so the default config must opt out to avoid a spurious warning.\n      sentinelClientConfig = DefaultJedisClientConfig.builder().serverDefaultProtocol().build();\n    }\n\n    return super.build();\n  }\n\n}\n","sourceCodeStart":86,"sourceCodeEnd":121,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/builders/SentinelClientBuilder.java#L86-L121","documentation":"A Sentinel client needs at least one sentinel address to query for the current master location and to subscribe to failover events. SentinelClientBuilder.validateSpecificConfiguration() throws this IllegalArgumentException when the sentinel endpoint set is null or empty at build() time.","triggerScenarios":"Building a RedisSentinelClient without calling .sentinels(...), or with an empty set of HostAndPort entries.","commonSituations":"Sentinel addresses parsed from config where the sentinel list key is missing or empty; split-string parsing producing an empty list for a blank config value; reusing a standalone connection config in sentinel mode.","solutions":["Provide sentinel endpoints via .sentinels(Set.of(new HostAndPort(\"sentinel1\", 26379), ...)) before build().","Validate the sentinel list is non-empty when parsing from configuration.","Confirm sentinel processes are actually deployed and reachable; the builder requires addresses regardless."],"exampleFix":"// before\nRedisSentinelClient client = RedisSentinelClient.builder()\n    .masterName(\"mymaster\")\n    .build(); // throws: no sentinels\n// after\nRedisSentinelClient client = RedisSentinelClient.builder()\n    .masterName(\"mymaster\")\n    .sentinels(Set.of(new HostAndPort(\"localhost\", 26379)))\n    .build();","handlingStrategy":"validation","validationCode":"if (sentinels == null || sentinels.isEmpty()) {\n  throw new IllegalArgumentException(\"at least one sentinel address is required\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Parse sentinel addresses with a tokenizer that rejects blank input instead of yielding an empty list.","List at least 3 sentinel endpoints for quorum reliability.","Verify sentinel reachability with a health check at startup."],"tags":["jedis","sentinel","builder","configuration","missing-nodes"],"backgroundTag":"missing-required-config-field","analyzedSha":"6dac31d4c224fb3257c216f3985340c6f500cdcb","analyzedAt":"2026-09-08T04:55:01.204Z","contentChangedAt":"2026-09-08T04:55:01.204Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}