{"record":{"id":"595dc506eac2521a","repo":"redis/jedis","slug":"cannot-get-connection-for-command-with-multiple-ha","errorCode":null,"errorMessage":"Cannot get connection for command with multiple hash slots","messagePattern":"Cannot get connection for command with multiple hash slots","errorType":"exception","errorClass":"JedisClusterOperationException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java","lineNumber":131,"sourceCode":"\n  public Map<String, ConnectionPool> getPrimaryNodes() {\n    return cache.getPrimaryNodes();\n  }\n\n  public HostAndPort getNode(int slot) {\n    return slot >= 0 ? cache.getSlotNode(slot) : null;\n  }\n\n  public Connection getConnection(HostAndPort node) {\n    return node != null ? cache.setupNodeIfNotExist(node).getResource() : getConnection();\n  }\n\n  @Override\n  public Connection getConnection(CommandArguments args) {\n    Set<Integer> slots = args.getKeyHashSlots();\n\n    if (slots.size() > 1) {\n      throw new JedisClusterOperationException(\"Cannot get connection for command with multiple hash slots\");\n    }\n\n    int slot = slots.iterator().next();\n    return slot >= 0 ? getConnectionFromSlot(slot) : getConnection();\n  }\n\n  public Connection getReplicaConnection(CommandArguments args) {\n    Set<Integer> slots = args.getKeyHashSlots();\n\n    if (slots.size() > 1) {\n      throw new JedisClusterOperationException(\"Cannot get connection for command with multiple hash slots\");\n    }\n\n    int slot = slots.iterator().next();\n    return slot >= 0 ? getReplicaConnectionFromSlot(slot) : getConnection();\n  }\n\n  @Override","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java#L113-L149","documentation":"ClusterConnectionProvider.getConnection() computes the hash slots of all keys in the command; Redis cluster commands must touch exactly one slot, so if the CommandArguments contain keys hashing to more than one slot it throws JedisClusterOperationException instead of sending an invalid cross-slot command.","triggerScenarios":"Issuing a multi-key command (e.g. MGET, MSET, SUNION, DEL of several keys, pipelines with multiple keys per command) whose keys hash to different slots on a cluster connection.","commonSituations":"Multi-key operations after re-sharding moved keys into different slots; pipelines reused between standalone and cluster modes; batch code that assumes all keys share a keytag/prefix.","solutions":["Split the operation into per-slot commands (group keys by hash slot) and issue one command per slot.","Use hash tags ({user1000}.field) so related keys colocate in the same slot.","Use a pipeline on the cluster client (which routes per-slot automatically) instead of a single multi-key command."],"exampleFix":"// before\njedis.mget(\"user:1\", \"order:2\"); // different slots\n// after\njedis.mget(\"{user:1}:a\", \"{user:1}:b\"); // same slot via hash tag","handlingStrategy":"validation","validationCode":"Set<Integer> slots = new HashSet<>();\nfor (String key : keys) slots.add(JedisClusterCRC16.getSlot(SafeEncoder.encode(key)));\nif (slots.size() > 1) throw new IllegalArgumentException(\"Keys span multiple cluster slots: \" + slots);","typeGuard":"boolean singleSlot(List<String> keys) { return keys.stream().map(k -> JedisClusterCRC16.getSlot(k.getBytes(StandardCharsets.UTF_8))).distinct().count() <= 1; }","tryCatchPattern":"try {\n  return jedis.mget(keys.toArray(new String[0]));\n} catch (JedisClusterOperationException e) {\n  return keys.stream().collect(partitioningBySlot()).values().stream()\n      .map(group -> jedis.mget(group.toArray(new String[0])))\n      .flatMap(List::stream).collect(toList());\n}","preventionTips":["Use hash tags ({user123}.field) to colocate related keys.","Group keys by JedisClusterCRC16.getSlot() before multi-key commands.","Prefer cluster pipelines over raw multi-key commands.","Test multi-key paths against a real cluster topology."],"tags":["jedis","cluster","hash-slots","redis"],"backgroundTag":"unsupported-operation","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"}