{"record":{"id":"c23823d4b06114f0","repo":"redisson/redisson","slug":"unable-to-find-master-node-c23823","errorCode":null,"errorMessage":"Unable to find master node: {}","messagePattern":"Unable to find master node: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"redisson-spring/redisson-spring-data/redisson-spring-data-22/src/main/java/org/redisson/spring/data/connection/RedissonClusterConnection.java","lineNumber":85,"sourceCode":"                new ObjectDecoder(new RedisClusterNodeDecoder(executorService.getServiceManager())));\n        return read(null, StringCodec.INSTANCE, cluster);\n    }\n\n    @Override\n    public Collection<RedisClusterNode> clusterGetSlaves(RedisClusterNode master) {\n        Iterable<RedisClusterNode> res = clusterGetNodes();\n        RedisClusterNode masterNode = null;\n        for (Iterator<RedisClusterNode> iterator = res.iterator(); iterator.hasNext();) {\n            RedisClusterNode redisClusterNode = iterator.next();\n            if (master.getHost().equals(redisClusterNode.getHost()) \n                    && master.getPort().equals(redisClusterNode.getPort())) {\n                masterNode = redisClusterNode;\n                break;\n            }\n        }\n        \n        if (masterNode == null) {\n            throw new IllegalStateException(\"Unable to find master node: \" + master);\n        }\n        \n        for (Iterator<RedisClusterNode> iterator = res.iterator(); iterator.hasNext();) {\n            RedisClusterNode redisClusterNode = iterator.next();\n            if (redisClusterNode.getMasterId() == null \n                    || !redisClusterNode.getMasterId().equals(masterNode.getId())) {\n                iterator.remove();\n            }\n        }\n        return (Collection<RedisClusterNode>) res;\n    }\n\n    @Override\n    public Map<RedisClusterNode, Collection<RedisClusterNode>> clusterGetMasterSlaveMap() {\n        Iterable<RedisClusterNode> res = clusterGetNodes();\n        \n        Set<RedisClusterNode> masters = new HashSet<RedisClusterNode>();\n        for (Iterator<RedisClusterNode> iterator = res.iterator(); iterator.hasNext();) {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/redisson/redisson/blob/91188987c2a9023e7fedabff758681ad9b107f25/redisson-spring/redisson-spring-data/redisson-spring-data-22/src/main/java/org/redisson/spring/data/connection/RedissonClusterConnection.java#L67-L103","documentation":"RedissonClusterConnection resolves slave replicas by matching the configured master host/port against the cluster node list obtained via clusterGetNodes(). If no node in the topology view matches the master's host and port, the connection's view of the cluster is stale or misconfigured, and it throws IllegalStateException naming the master it could not find.","triggerScenarios":"Calling clusterGetReplicas(master) / getClusterClusterConnection slave resolution when the cluster topology changed (failover, resharding, node restart with new address) or when the Config's master address does not exactly match a node's host/port in CLUSTER NODES output (e.g. DNS name vs IP mismatch).","commonSituations":"Cluster failover just happened and the client holds an old topology; connecting through a proxy/Docker NAT where the advertised host differs from the configured address; mixed use of hostnames and IPs between config and cluster announcements.","solutions":["Make the configured master address match what the cluster announces (use the same hostnames/IPs the nodes advertise in CLUSTER NODES)","Trigger a topology refresh / recreate the Redisson client after a failover so clusterGetNodes() returns current data","In containerized environments, ensure announce-ip/announce-port (or Docker NAT settings) are consistent across all nodes"],"exampleFix":"// before\nconfig.useClusterServers()\n      .addNodeAddress(\"redis://10.0.0.5:6379\"); // cluster announces redis-master:6379\n\n// after\nconfig.useClusterServers()\n      .addNodeAddress(\"redis://redis-master:6379\"); // matches announced host:port","handlingStrategy":"try-catch","validationCode":"// Pre-check that the configured master appears in the topology before asking for replicas:\nRedisClusterNode match = StreamSupport.stream(clusterGetNodes().spliterator(), false)\n        .filter(n -> n.getHost().equals(master.getHost()) && n.getPort() == master.getPort())\n        .findFirst().orElse(null);\nif (match == null) { /* refresh topology / re-create client */ }","typeGuard":null,"tryCatchPattern":"try {\n    Collection<RedisClusterNode> replicas = connection.clusterGetReplicas(master);\n} catch (IllegalStateException e) {\n    if (e.getMessage().startsWith(\"Unable to find master node\")) {\n        // topology drift: refresh cluster topology or rebuild RedissonClient, then retry once\n    }\n}","preventionTips":["Configure node addresses exactly as the cluster announces them (hostnames vs IPs must match)","In Docker/K8s, set consistent announce-ip/announce-port on all nodes","Recreate or refresh the Redisson client after cluster failovers instead of caching connections indefinitely"],"tags":["redis","redisson","cluster","topology","failover","docker-nat"],"backgroundTag":null,"analyzedSha":"91188987c2a9023e7fedabff758681ad9b107f25","analyzedAt":"2026-08-14T11:39:42.619Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}