{"record":{"id":"36f224b0ec98d3dd","repo":"redisson/redisson","slug":"sentinels-are-offline-36f224","errorCode":null,"errorMessage":"Sentinels are offline","messagePattern":"Sentinels are offline","errorType":"exception","errorClass":"InvalidDataAccessResourceUsageException","httpStatus":null,"severity":"critical","filePath":"redisson-spring/redisson-spring-data/redisson-spring-data-24/src/main/java/org/redisson/spring/data/connection/RedissonConnectionFactory.java","lineNumber":161,"sourceCode":"\n        SentinelConnectionManager manager = (SentinelConnectionManager)(((Redisson)redisson).getCommandExecutor().getConnectionManager());\n        for (RedisClient client : manager.getSentinels()) {\n            org.redisson.client.RedisConnection connection = null;\n            try {\n                connection = client.connect();\n                String res = connection.sync(RedisCommands.PING);\n                if (\"pong\".equalsIgnoreCase(res)) {\n                    return new RedissonSentinelConnection(connection);\n                }\n            } catch (Exception e) {\n                log.warn(\"Can't connect to \" + client, e);\n                if (connection != null) {\n                    connection.closeAsync();\n                }\n            }\n        }\n\n        throw new InvalidDataAccessResourceUsageException(\"Sentinels are offline\");\n    }\n\n    @Override\n    public ReactiveRedisConnection getReactiveConnection() {\n        if (redisson.getConfig().isClusterConfig()) {\n            return new RedissonReactiveRedisClusterConnection(((RedissonReactive)redisson.reactive()).getCommandExecutor());\n        }\n\n        return new RedissonReactiveRedisConnection(((RedissonReactive)redisson.reactive()).getCommandExecutor());\n    }\n\n    @Override\n    public ReactiveRedisClusterConnection getReactiveClusterConnection() {\n        if (!redisson.getConfig().isClusterConfig()) {\n            throw new InvalidDataAccessResourceUsageException(\"Redisson is not in Cluster mode\");\n        }\n\n        return new RedissonReactiveRedisClusterConnection(((RedissonReactive)redisson.reactive()).getCommandExecutor());","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/redisson/redisson/blob/91188987c2a9023e7fedabff758681ad9b107f25/redisson-spring/redisson-spring-data/redisson-spring-data-24/src/main/java/org/redisson/spring/data/connection/RedissonConnectionFactory.java#L143-L179","documentation":"getSentinelConnection() iterates all configured sentinel addresses, opens a direct connection to each and PINGs it; if none respond (connect fails, throws, or wrong reply) it throws InvalidDataAccessResourceUsageException with 'Sentinels are offline'. Each failure is logged at WARN with the client address before the exception is raised.","triggerScenarios":"Redisson configured with useSentinelServers() but every sentinel host in sentinelAddresses is unreachable (network partition, wrong host/port, firewall) or responds abnormally, so the loop in RedissonConnectionFactory exhausts all sentinels.","commonSituations":"Sentinel ports not exposed in Docker/Kubernetes; stale sentinel IPs after infra migration; DNS resolving but service down; application starting while the sentinel cluster itself is restarting; typos in sentinel addresses.","solutions":["Verify each sentinel is reachable from the app host: redis-cli -h <sentinel-host> -p <sentinel-port> ping","Fix the sentinelAddresses list in the Redisson config (correct hosts/ports, expose ports in Docker/K8s, update security groups)","Check the WARN logs ('Can't connect to ...') just before the exception to see exactly which sentinel endpoints failed and why (DNS, timeout, auth)","If sentinels require auth, ensure sentinelPassword/username are set in the config so the direct PING succeeds"],"exampleFix":"// before\nConfig config = Config.useSentinelServers()\n    .setSentinelAddresses(List.of(\"redis://sentinel:26379\"))\n    .setMasterName(\"mymaster\");\nRedisSentinelConnection s = new RedissonConnectionFactory(Redisson.create(config)).getSentinelConnection(); // Sentinels are offline\n\n// after\n// verify: redis-cli -h sentinel -p 26379 ping  => PONG\nConfig config = Config.useSentinelServers()\n    .setSentinelAddresses(List.of(\"redis://10.0.1.5:26379\", \"redis://10.0.1.6:26379\", \"redis://10.0.1.7:26379\"))\n    .setMasterName(\"mymaster\");\nRedisSentinelConnection s = new RedissonConnectionFactory(Redisson.create(config)).getSentinelConnection();","handlingStrategy":"retry","validationCode":"// pre-flight: ensure at least one sentinel answers PING before requesting the connection\nboolean anyUp = sentinelAddresses.stream().anyMatch(addr -> {\n    try (var jedis = new Jedis(hostOf(addr), portOf(addr))) {\n        return \"PONG\".equalsIgnoreCase(jedis.ping());\n    } catch (Exception e) { return false; }\n});\nif (!anyUp) throw new IllegalStateException(\"no sentinel reachable\");","typeGuard":null,"tryCatchPattern":"try {\n    return factory.getSentinelConnection();\n} catch (InvalidDataAccessResourceUsageException e) {\n    if (\"Sentinels are offline\".equals(e.getMessage())) {\n        // backoff and retry; sentinels may be restarting\n        Thread.sleep(backoffMs);\n        return factory.getSentinelConnection();\n    }\n    throw e;\n}","preventionTips":["Run startup connectivity checks against every sentinel address before the app starts serving","Expose sentinel ports in Docker/K8s and allow them in firewall/security groups","Configure multiple sentinels so one being down does not exhaust the loop","Monitor the WARN 'Can't connect to' log lines as an early signal of sentinel reachability problems"],"tags":["redis","sentinel","network","connectivity"],"backgroundTag":null,"analyzedSha":"91188987c2a9023e7fedabff758681ad9b107f25","analyzedAt":"2026-08-14T11:39:42.619Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}