redis/jedis · error · IllegalArgumentException
Unsupported key type
Error message
Unsupported key type: ${preprocessedKey.getClass().getName()} What it means
ClusterCommandObjects.calculateSlotFromPreprocessedKey computes the Redis Cluster hash slot for a key, but only understands byte[], String, and Rawable key representations. When a command is built with a key object of any other type, it cannot be routed to a cluster node, so an IllegalArgumentException is thrown naming the offending class.
Solutions
- Convert the key to a supported type before passing it: call key.toString(), SafeEncoder.encode(key), or implement redis.clients.jedis.args.Rawable returning the encoded bytes.
- If the key is a custom wrapper, extract the underlying String or byte[] representation at the call site.
- Check for a version/API change: ensure you are passing the raw key value, not a CommandObject or other internal type, to the command method.
Example fix
// before cluster.set(myKeyWrapper, value); // myKeyWrapper is a custom type // after cluster.set(myKeyWrapper.toString(), value);
Defensive patterns
Strategy: type-guard
Validate before calling
private static Object toClusterKey(Object key) {
if (key instanceof String || key instanceof byte[] || key instanceof redis.clients.jedis.args.Rawable) return key;
return key.toString();
} Type guard
static boolean isClusterKey(Object k) {
return k instanceof String || k instanceof byte[] || k instanceof redis.clients.jedis.args.Rawable;
} Try / catch
try {
cluster.set(key, value);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unsupported key type")) {
cluster.set(key.toString(), value);
} else throw e;
} Prevention
- Always pass keys as String or byte[] in cluster mode.
- Encode custom key objects with SafeEncoder.encode() before use.
- Centralize key construction in one helper that normalizes types.
When it happens
Trigger: Calling any cluster command via UnifiedJedis/ClusterCommandObjects with a key argument that is neither byte[], String, nor a Rawable — e.g. a custom key wrapper object, an Integer/Long passed where a key is expected, or a CommandObject built with an unsupported preprocessed key type.
Common situations: Migrating code from a standalone Jedis setup to RedisClusterClient where keys were passed as arbitrary objects; wrapping keys in custom domain types and forgetting to call toString() or serialize; library users passing protocol objects that are neither byte[] nor Rawable.
Related errors
- " " is not a valid argument.
- Cluster mode only supports SCAN command with MATCH pattern…
- Not supported in cluster mode.
- Cannot get NodeKey for command with multiple hash slots
- null is not a valid argument.
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/4a23c96ab14f70b4.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/ClusterCommandObjects.java:357
return result;
}
/**
* Calculates the hash slot for a preprocessed key.
*
* @param preprocessedKey the key after preprocessing (may be String, byte[], or Rawable)
* @return the hash slot for the key
*/
private int calculateSlotFromPreprocessedKey(Object preprocessedKey) {
if (preprocessedKey instanceof byte[]) {
return JedisClusterCRC16.getSlot((byte[]) preprocessedKey);
} else if (preprocessedKey instanceof String) {
return JedisClusterCRC16.getSlot((String) preprocessedKey);
} else if (preprocessedKey instanceof redis.clients.jedis.args.Rawable) {
return JedisClusterCRC16.getSlot(((redis.clients.jedis.args.Rawable) preprocessedKey).getRaw());
}
throw new IllegalArgumentException("Unsupported key type: " + preprocessedKey.getClass().getName());
}
/**
* Helper method to create a CommandArguments for a group of keys/values.
*/
private <T> CommandArguments createCommandArgsForGroup(
CommandArguments args,
List<T> groupedElements,
IParams params,
BiConsumer<CommandArguments, T> keyAdder,
BiConsumer<CommandArguments, T> valueAdder,
boolean insertKeyCount,
int step) {
boolean keyValueMode = valueAdder != null;
CommandArguments slotArgs = commandArguments(args.getCommand());
// Insert key count after command but before keys (e.g., numkeys for MSETEX)View on GitHub (pinned to 6dac31d4c2)