redisson/redisson · error · IllegalStateException
Unable to find master node: ${master}
Error message
Unable to find master node: ${master} What it means
RedissonClusterConnection.getSlaveConnection/getMasterConnection-style node resolution (method at RedissonClusterConnection.java:85, redisson-spring-data-20) throws IllegalStateException('Unable to find master node: <node>') when the node requested by the caller is not present in the topology returned by clusterGetNodes(). The lookup matches host AND port, so any host/port/id mismatch (e.g. after failover or resharding, or when nodes report internal IPs) makes masterNode null.
Source
Thrown at redisson-spring/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/RedissonClusterConnection.java:85
new ObjectDecoder(new RedisClusterNodeDecoder(executorService.getServiceManager())));
return read(null, StringCodec.INSTANCE, cluster);
}
@Override
public Collection<RedisClusterNode> clusterGetSlaves(RedisClusterNode master) {
Iterable<RedisClusterNode> res = clusterGetNodes();
RedisClusterNode masterNode = null;
for (Iterator<RedisClusterNode> iterator = res.iterator(); iterator.hasNext();) {
RedisClusterNode redisClusterNode = iterator.next();
if (master.getHost().equals(redisClusterNode.getHost())
&& master.getPort().equals(redisClusterNode.getPort())) {
masterNode = redisClusterNode;
break;
}
}
if (masterNode == null) {
throw new IllegalStateException("Unable to find master node: " + master);
}
for (Iterator<RedisClusterNode> iterator = res.iterator(); iterator.hasNext();) {
RedisClusterNode redisClusterNode = iterator.next();
if (redisClusterNode.getMasterId() == null
|| !redisClusterNode.getMasterId().equals(masterNode.getId())) {
iterator.remove();
}
}
return (Collection<RedisClusterNode>) res;
}
@Override
public Map<RedisClusterNode, Collection<RedisClusterNode>> clusterGetMasterSlaveMap() {
Iterable<RedisClusterNode> res = clusterGetNodes();
Set<RedisClusterNode> masters = new HashSet<RedisClusterNode>();
for (Iterator<RedisClusterNode> iterator = res.iterator(); iterator.hasNext();) {View on GitHub (pinned to 91188987c2)
Solutions
- Always obtain RedisClusterNode instances from clusterGetNodes()/clusterGetSlots() at call time instead of caching or constructing them manually
- Refresh the node view (clusterGetNodes) and retry once when this exception occurs
- For NAT/Docker deployments configure cluster-announce-ip / cluster-announce-port so advertised host:port match what the client sees
- Match by node Id when possible rather than host:port, since Ids are stable across DNS changes
Example fix
// before
RedisClusterNode stale = cachedNode; // captured minutes ago
connection.getClientList(stale); // may throw after failover
// after
RedisClusterNode master = connection.clusterGetNodes().stream()
.filter(n -> n.getId().equals(wantedId))
.findFirst().orElseThrow();
connection.getClientList(master); Defensive patterns
Strategy: fallback
Validate before calling
// Resolve nodes fresh and match by stable Id before node-specific calls
Collection<RedisClusterNode> nodes = clusterConnection.clusterGetNodes();
Optional<RedisClusterNode> target = nodes.stream()
.filter(n -> n.getId().equals(wantedId))
.findFirst();
if (!target.isPresent()) {
nodes = clusterConnection.clusterGetNodes(); // refresh topology once
target = nodes.stream().filter(n -> n.getId().equals(wantedId)).findFirst();
}
// proceed only if target.isPresent() Type guard
Optional<RedisClusterNode> resolveNode(RedisClusterConnection c, String nodeId) {
return c.clusterGetNodes().stream()
.filter(n -> n.getId().equals(nodeId)).findFirst();
} Try / catch
catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().contains("Unable to find master node")) {
// refresh clusterGetNodes() and retry once; else surface topology-change alert
} else throw e;
} Prevention
- Never cache RedisClusterNode across requests; re-resolve each time
- Prefer node Id over host:port for lookups
- Configure cluster-announce-ip/port in NAT/Docker clusters
- Retry once on topology errors to ride through failovers
When it happens
Trigger: Passing a RedisClusterNode to a node-specific operation (e.g. getClientList(node), node-specific reads/writes) whose host:port does not exactly equal any node in CLUSTER NODES output — typically because the caller cached a stale node view, the cluster failed over, or NAT/Docker maps advertised ports differently.
Common situations: Redis Cluster in Docker/K8s with NAT where nodes advertise internal IPs (announcedIP missing); a cached RedisClusterNode from a previous topology used after failover; comparing a node built from config (e.g. 127.0.0.1:7000) with the topology entry (10.0.0.5:7000); slot migration in progress.
Related errors
- Unable to find master node: {}
- Unable to find master node:
- Unable to find master node:
- hibernate.cache.redisson.jndi_name property not set
- Unable to find master node: {}
AI-assisted analysis of redisson/redisson@91188987c2 (2026-08-14).
Data as JSON: /api/errors/66df4d6e8ab3a959.
Report an issue: GitHub.