redis/jedis · error · UnsupportedOperationException

Support only execute to replica in ClusterCommandExecutor

Error message

Support only execute to replica in ClusterCommandExecutor

What it means

RedisClusterClient.executeCommandToReplica() delegates replica routing to its internal CommandExecutor. Replica reads are only implemented by ClusterCommandExecutor; if the client was built with a different executor, the method throws UnsupportedOperationException rather than silently mis-routing the command. It is an explicit capability check on the configured executor.

Solutions

  1. Build the client with the default RedisClusterClient builder so it uses ClusterCommandExecutor.
  2. Remove the custom executor override (or the code path calling executeCommandToReplica) when not in cluster mode.
  3. If you need replica reads in non-cluster mode, use an API supported by that executor instead.

Example fix

// before
RedisClusterClient client = RedisClusterClient.builder()
    .executor(new RetryCommandExecutor(provider, cache))
    .build();
client.executeCommandToReplica(cmdObj); // throws

// after
RedisClusterClient client = RedisClusterClient.builder()
    .nodes(nodes)
    .build(); // uses ClusterCommandExecutor
client.executeCommandToReplica(cmdObj);
Defensive patterns

Strategy: fallback

Validate before calling

boolean supportsReplicaReads = client instanceof RedisClusterClient;
if (!supportsReplicaReads) {
  throw new IllegalStateException("Replica reads require RedisClusterClient");
}

Type guard

boolean canExecuteToReplica(RedisClusterClient c) {
  return c != null; // replica routing requires the default cluster executor
}

Try / catch

try {
  return client.executeCommandToReplica(cmd);
} catch (UnsupportedOperationException e) {
  return client.sendCommand(cmd); // fallback to primary
}

Prevention

When it happens

Trigger: Calling executeCommandToReplica(commandObject) on a RedisClusterClient whose executor is not a ClusterCommandExecutor — e.g. after overriding the executor via a custom builder configuration or using a subclass that plugs in DefaultCommandExecutor/RetryCommandExecutor.

Common situations: Custom client builders or tests that substitute a non-cluster executor; code copied from a cluster setup into a standalone/single-node configuration; library-internal subclassing where validateSpecificConfiguration was bypassed.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08). Data as JSON: /api/errors/ba10af853458b680. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/redis/clients/jedis/RedisClusterClient.java:266

            (ClusterConnectionProvider) provider,
            (ClusterCommandObjects) commandObjects,
            commandFlagsRegistry,
            executorService
    );
  }
  /**
   * @param doMulti param
   * @return nothing
   * @throws UnsupportedOperationException
   */
  @Override
  public AbstractTransaction transaction(boolean doMulti) {
    throw new UnsupportedOperationException();
  }

  public final <T> T executeCommandToReplica(CommandObject<T> commandObject) {
    if (!(executor instanceof ClusterCommandExecutor)) {
      throw new UnsupportedOperationException(
          "Support only execute to replica in ClusterCommandExecutor");
    }
    return ((ClusterCommandExecutor) executor).executeCommandToReplica(commandObject);
  }

  /**
   * Broadcast a command to all primary nodes in the cluster.
   * <p>
   * This method is useful for administrative commands that need to be executed on all primary nodes,
   * such as {@code PING}, {@code CONFIG SET}, {@code FLUSHALL}, etc.
   * </p>
   * @param commandObject the command to broadcast
   * @param <T> the return type of the command
   * @return the aggregated reply from all primary nodes
   * @throws UnsupportedOperationException if the executor is not a ClusterCommandExecutor
   */
  public final <T> T broadcastCommand(CommandObject<T> commandObject) {
    if (!(executor instanceof ClusterCommandExecutor)) {

View on GitHub (pinned to 6dac31d4c2)