redisson/redisson · critical · InvalidDataAccessResourceUsageException

Sentinels are offline

Error message

Sentinels are offline

What it means

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.

Source

Thrown at redisson-spring/redisson-spring-data/redisson-spring-data-24/src/main/java/org/redisson/spring/data/connection/RedissonConnectionFactory.java:161

        SentinelConnectionManager manager = (SentinelConnectionManager)(((Redisson)redisson).getCommandExecutor().getConnectionManager());
        for (RedisClient client : manager.getSentinels()) {
            org.redisson.client.RedisConnection connection = null;
            try {
                connection = client.connect();
                String res = connection.sync(RedisCommands.PING);
                if ("pong".equalsIgnoreCase(res)) {
                    return new RedissonSentinelConnection(connection);
                }
            } catch (Exception e) {
                log.warn("Can't connect to " + client, e);
                if (connection != null) {
                    connection.closeAsync();
                }
            }
        }

        throw new InvalidDataAccessResourceUsageException("Sentinels are offline");
    }

    @Override
    public ReactiveRedisConnection getReactiveConnection() {
        if (redisson.getConfig().isClusterConfig()) {
            return new RedissonReactiveRedisClusterConnection(((RedissonReactive)redisson.reactive()).getCommandExecutor());
        }

        return new RedissonReactiveRedisConnection(((RedissonReactive)redisson.reactive()).getCommandExecutor());
    }

    @Override
    public ReactiveRedisClusterConnection getReactiveClusterConnection() {
        if (!redisson.getConfig().isClusterConfig()) {
            throw new InvalidDataAccessResourceUsageException("Redisson is not in Cluster mode");
        }

        return new RedissonReactiveRedisClusterConnection(((RedissonReactive)redisson.reactive()).getCommandExecutor());

View on GitHub (pinned to 91188987c2)

Solutions

  1. Verify each sentinel is reachable from the app host: redis-cli -h <sentinel-host> -p <sentinel-port> ping
  2. Fix the sentinelAddresses list in the Redisson config (correct hosts/ports, expose ports in Docker/K8s, update security groups)
  3. Check the WARN logs ('Can't connect to ...') just before the exception to see exactly which sentinel endpoints failed and why (DNS, timeout, auth)
  4. If sentinels require auth, ensure sentinelPassword/username are set in the config so the direct PING succeeds

Example fix

// before
Config config = Config.useSentinelServers()
    .setSentinelAddresses(List.of("redis://sentinel:26379"))
    .setMasterName("mymaster");
RedisSentinelConnection s = new RedissonConnectionFactory(Redisson.create(config)).getSentinelConnection(); // Sentinels are offline

// after
// verify: redis-cli -h sentinel -p 26379 ping  => PONG
Config config = Config.useSentinelServers()
    .setSentinelAddresses(List.of("redis://10.0.1.5:26379", "redis://10.0.1.6:26379", "redis://10.0.1.7:26379"))
    .setMasterName("mymaster");
RedisSentinelConnection s = new RedissonConnectionFactory(Redisson.create(config)).getSentinelConnection();
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: ensure at least one sentinel answers PING before requesting the connection
boolean anyUp = sentinelAddresses.stream().anyMatch(addr -> {
    try (var jedis = new Jedis(hostOf(addr), portOf(addr))) {
        return "PONG".equalsIgnoreCase(jedis.ping());
    } catch (Exception e) { return false; }
});
if (!anyUp) throw new IllegalStateException("no sentinel reachable");

Try / catch

try {
    return factory.getSentinelConnection();
} catch (InvalidDataAccessResourceUsageException e) {
    if ("Sentinels are offline".equals(e.getMessage())) {
        // backoff and retry; sentinels may be restarting
        Thread.sleep(backoffMs);
        return factory.getSentinelConnection();
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of redisson/redisson@91188987c2 (2026-08-14). Data as JSON: /api/errors/36f224b0ec98d3dd. Report an issue: GitHub.