redis/jedis · error · IllegalArgumentException

protocol must not be null

Error message

protocol must not be null

What it means

The CommandObjects constructor requires a non-null RedisProtocol (RESP2 or RESP3) because protocol version affects command encoding and behavior. Passing null means the client was constructed without specifying a protocol, so IllegalArgumentException is thrown at construction time.

Solutions

  1. Pass an explicit protocol, e.g. new CommandObjects(RedisProtocol.RESP3), or the protocol configured on your client.
  2. If using a builder, call .protocol(...) or ensure the default protocol is set before build().
  3. Guard the wiring: assert protocol != null (or default to RedisProtocol.RESP2) before constructing CommandObjects.

Example fix

// before
CommandObjects commandObjects = new CommandObjects(protocol); // protocol may be null
// after
RedisProtocol protocol = configuredProtocol != null ? configuredProtocol : RedisProtocol.RESP3;
CommandObjects commandObjects = new CommandObjects(protocol);
Defensive patterns

Strategy: validation

Validate before calling

RedisProtocol protocol = Optional.ofNullable(configuredProtocol).orElse(RedisProtocol.RESP3);
CommandObjects co = new CommandObjects(protocol);

Type guard

static RedisProtocol requireProtocol(RedisProtocol p) {
  if (p == null) throw new IllegalArgumentException("protocol must be set before building client");
  return p;
}

Try / catch

try {
  CommandObjects co = new CommandObjects(protocol);
} catch (IllegalArgumentException e) {
  if ("protocol must not be null".equals(e.getMessage())) {
    protocol = RedisProtocol.RESP3;
  } else throw e;
}

Prevention

When it happens

Trigger: Constructing CommandObjects (or a client/builder that instantiates it) with a null RedisProtocol — e.g. a builder field left unset, ProtocolArgument/protocol config not initialized, or calling new CommandObjects(null) directly in custom executor/provider code.

Common situations: Custom UnifiedJedis subclasses or test fixtures building CommandObjects manually; a client builder whose protocol() was never called and whose default was null; reflection or DI wiring that failed to supply the protocol.

Related errors


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

Appendix: source

Thrown at src/main/java/redis/clients/jedis/CommandObjects.java:45

import redis.clients.jedis.search.SearchProtocol.*;
import redis.clients.jedis.search.SearchResult.SearchResultBuilder;
import redis.clients.jedis.search.aggr.AggregationBuilder;
import redis.clients.jedis.search.aggr.AggregationResult;
import redis.clients.jedis.search.hybrid.FTHybridParams;
import redis.clients.jedis.search.hybrid.HybridResult;
import redis.clients.jedis.search.schemafields.SchemaField;
import redis.clients.jedis.timeseries.*;
import redis.clients.jedis.timeseries.TimeSeriesProtocol.*;
import redis.clients.jedis.util.KeyValue;
import redis.clients.jedis.util.CompareCondition;

public class CommandObjects {

  private final RedisProtocol protocol;

  public CommandObjects(RedisProtocol protocol) {
    if (protocol == null) {
      throw new IllegalArgumentException("protocol must not be null");
    }
    this.protocol = protocol;
  }

  // TODO: remove?
  protected RedisProtocol getProtocol() {
    return protocol;
  }

  protected volatile CommandKeyArgumentPreProcessor keyPreProcessor = null;
  private Lock mapperLock = new ReentrantLock(true);
  private volatile JsonObjectMapper jsonObjectMapper;
  private final AtomicInteger searchDialect = new AtomicInteger(SearchProtocol.DEFAULT_DIALECT);

  @Experimental
  public void setKeyArgumentPreProcessor(CommandKeyArgumentPreProcessor keyPreProcessor) {
    this.keyPreProcessor = keyPreProcessor;
  }

View on GitHub (pinned to 6dac31d4c2)