redis/jedis · error · UnsupportedAggregationException

requires Boolean, Long, ArrayList , or ArrayList , but got

Error message

${operationName} requires Boolean, Long, ArrayList<Boolean>, or ArrayList<Long>, but got: ${input.getClass().getName()}

What it means

LogicalBinaryAggregator merges Boolean/Long replies from a two-shard logical broadcast (e.g. EXISTS-style checks with ALL-SUCC / ANY-SUCC policies). The first non-null input must be Boolean, Long, or an ArrayList; anything else throws UnsupportedAggregationException with the actual type. It enforces that logical operations only aggregate boolean-like results.

Solutions

  1. Ensure the command's Builder converts replies to Boolean or Long (BuilderFactory.BOOLEAN / LONG) before aggregation.
  2. Use a non-logical response policy if the command genuinely returns other types.
  3. For multi-value results, parse into ArrayList<Boolean>/ArrayList<Long> so the aggregator accepts them.

Example fix

// before
new CommandObject<>(args, BuilderFactory.STRING)   // String fed to logical aggregator
// after
new CommandObject<>(args, BuilderFactory.BOOLEAN)  // Boolean accepted by logical aggregator
Defensive patterns

Strategy: type-guard

Validate before calling

Object reply = jedis.sendCommand(cmd);
if (!(reply instanceof Boolean || reply instanceof Long || reply instanceof ArrayList)) {
  throw new IllegalStateException("logical broadcast requires Boolean/Long replies");
}

Type guard

boolean isLogicalReply(Object r) {
  return r instanceof Boolean || r instanceof Long || r instanceof ArrayList;
}

Try / catch

try {
  return logicalBroadcast();
} catch (UnsupportedAggregationException e) {
  logger.error("bad reply type for logical op: {}", e.getMessage());
  throw new IllegalStateException(e);
}

Prevention

When it happens

Trigger: Executing a multi-shard logical command (operationName like ANY-SUCC/ALL-SUCC aggregation) whose Builder produces a reply type other than Boolean/Long/ArrayList — e.g. a String status reply or a byte[] being aggregated.

Common situations: Custom or module commands registered with a logical response policy but parsed to String/byte[]; wiring a broadcast EXISTS-like command with a generic OBJECT builder instead of BuilderFactory.BOOLEAN/LONG.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/redis/clients/jedis/executors/aggregators/LogicalBinaryAggregator.java:31

  private final String operationName;

  protected LogicalBinaryAggregator(String operationName) {
    this.operationName = operationName;
  }

  @Override
  public void add(T input) {
    if (input == null) {
      return; // ignore nulls
    }

    if (result == null) {
      // First non-null input initializes the result
      if (input instanceof Boolean || input instanceof Long || input instanceof ArrayList) {
        result = input;
        return;
      } else {
        throw new UnsupportedAggregationException(operationName
            + " requires Boolean, Long, ArrayList<Boolean>, or ArrayList<Long>, but got: "
            + input.getClass().getName());
      }
    }

    // Handle Boolean
    if (result instanceof Boolean && input instanceof Boolean) {
      result = (T) Boolean.valueOf(applyBooleanOp((Boolean) result, (Boolean) input));
      return;
    }

    // Handle Long
    if (result instanceof Long && input instanceof Long) {
      boolean existingBool = (Long) result != 0;
      boolean newBool = (Long) input != 0;
      result = (T) Long.valueOf(applyBooleanOp(existingBool, newBool) ? 1L : 0L);
      return;
    }

View on GitHub (pinned to 6dac31d4c2)