redis/jedis · error · IllegalArgumentException
commandObjects must not be null or empty
Error message
commandObjects must not be null or empty
What it means
ClusterCommandExecutor.executeMultiShardCommand broadcasts a command to all shards and aggregates the replies according to the command's response policy. It throws IllegalArgumentException when the list of CommandObjects is null or empty, because there is nothing to route or a policy to derive. This is an input-validation guard at the entry of the broadcast API.
Solutions
- Ensure the list passed to executeMultiShardCommand contains at least one CommandObject before calling.
- If the list is built by filtering, check `list.isEmpty()` first and either skip the broadcast or return a sensible empty result instead.
- Fix the code that produces null lists (initialize collections to empty rather than null).
Example fix
// before
return executor.executeMultiShardCommand(commands);
// after
if (commands == null || commands.isEmpty()) {
throw new IllegalArgumentException("at least one command is required");
}
return executor.executeMultiShardCommand(commands); Defensive patterns
Strategy: validation
Validate before calling
if (commandObjects == null || commandObjects.isEmpty()) {
// skip broadcast or return an empty aggregated result
return null;
} Try / catch
try {
return executor.executeMultiShardCommand(commands);
} catch (IllegalArgumentException e) {
logger.warn("broadcast skipped: no commands", e);
return null;
} Prevention
- Initialize command collections as empty lists, never null
- Check list size before cluster-wide broadcast calls
- Centralize broadcast calls in a helper that guards the empty case
When it happens
Trigger: Calling `clusterClient executeMultiShardCommand(List)` with a null list, or with an empty list produced by filtering an empty key/command set (e.g. no commands matched a pattern before broadcasting).
Common situations: Cluster-wide commands (FLUSHDB, DBSIZE, CONFIG GET, keyspace scanning) built programmatically where the command list construction returned empty; calling broadcast APIs on a cluster client that hasn't had any commands registered.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Broadcast command is only supported in…
- AGG_SUM policy requires numeric type, but got
- Range must not be null.
- TS.NRANGE/TS.NREVRANGE require at least one key
- DIALECT=0 cannot be set.
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/7b885d3377dc7689.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/executors/ClusterCommandExecutor.java:159
* This method is designed for commands that need to operate on keys distributed across multiple
* hash slots (e.g., DEL, EXISTS, MGET with keys from different slots). Each CommandObject in the
* list is executed on its appropriate shard based on the key's hash slot, and the results are
* aggregated using the command's response policy.
* <p>
* Error handling depends on the command's response policy:
* <ul>
* <li>{@code ONE_SUCCEEDED}: Returns success if at least one shard succeeds</li>
* <li>Other policies: Throws {@link JedisBroadcastException} if any shard fails</li>
* </ul>
*
* @param commandObjects list of CommandObject instances, each targeting keys in the same hash slot
* @param <T> the return type of the command
* @return the aggregated reply from all shards
* @throws JedisBroadcastException if error handling criteria based on response policy are not met
*/
public final <T> T executeMultiShardCommand(List<CommandObject<T>> commandObjects) {
if (commandObjects == null || commandObjects.isEmpty()) {
throw new IllegalArgumentException("commandObjects must not be null or empty");
}
// Get the response policy from the first command (all commands should have the same policy)
CommandFlagsRegistry.ResponsePolicy responsePolicy = flags.getResponsePolicy(
commandObjects.get(0).getArguments());
MultiNodeResultAggregator<T> aggregator = new MultiNodeResultAggregator<>(responsePolicy);
for (CommandObject<T> commandObject : commandObjects) {
try {
// Execute each command on its appropriate shard using the existing retry logic
T aReply = doExecuteCommand(commandObject, slotBasedConnectionResolver, true);
aggregator.addSuccess(aReply);
} catch (Exception anError) {
// Extract node from exception (JedisClusterOperationException includes node info)
aggregator.addError(anError);
}
}View on GitHub (pinned to 6dac31d4c2)