redis/jedis · error · IllegalArgumentException

keysValues must contain an even number of elements…

Error message

keysValues must contain an even number of elements (key-value pairs)

What it means

A generic guard inside the private cluster-slot grouping helper: when the valueAdder (key-value pair mode) is used, keysOrKeysValues must alternate key,value entries; an odd-length array means a key or value is missing, so pairs cannot be split and routed to hash slots. Fires before any command is sent.

Solutions

  1. Fix the caller so the array passed to the command contains complete key,value pairs (even number of elements)
  2. Check array length before invoking the command and reject odd-length input early
  3. Use the keys-only variant (groupArgumentsByKeyHashSlot) if you intend to pass keys without values
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/main/java/redis/clients/jedis/ClusterCommandObjects.java:298 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at src/main/java/redis/clients/jedis/ClusterCommandObjects.java:298

   * @param insertKeyCount if true, inserts the number of keys after the command but before the keys (for commands like MSETEX)
   * @return a list of CommandArguments objects, each containing only keys/values that belong to the same hash slot,
   *         preserving the original key order
   * @throws IllegalArgumentException if valueAdder is provided and keysOrKeysValues has odd length
   */
  private <T> List<CommandArguments> groupArgumentsByKeyValueHashSlotImpl(
      CommandArguments args,
      T[] keysOrKeysValues,
      IParams params,
      Function<T, Integer> slotCalculator,
      BiConsumer<CommandArguments, T> keyAdder,
      BiConsumer<CommandArguments, T> valueAdder,
      boolean insertKeyCount) {

    boolean keyValueMode = valueAdder != null;
    int step = keyValueMode ? 2 : 1;

    if (keyValueMode && keysOrKeysValues.length % 2 != 0) {
      throw new IllegalArgumentException("keysValues must contain an even number of elements (key-value pairs)");
    }

    if (keysOrKeysValues.length == 0) {
      return new ArrayList<>();
    }

    // Wrap slotCalculator to apply keyPreProcessor transformation before slot calculation.
    // This ensures keys are grouped by their actual slot (after preprocessing), not the original key's slot.
    Function<T, Integer> effectiveSlotCalculator = keyPreProcessor != null
        ? key -> calculateSlotFromPreprocessedKey(keyPreProcessor.actualKey(key))
        : slotCalculator;

    // Group consecutive keys with the same slot together, preserving input order
    // Non-consecutive keys with the same slot will be in separate commands
    List<CommandArguments> result = new ArrayList<>();

    int currentSlot = -1;
    List<T> currentGroup = new ArrayList<>();

View on GitHub (pinned to 6dac31d4c2)