redis/jedis · error · JedisException

Client side caching is only supported with RESP3.

Error message

Client side caching is only supported with RESP3.

What it means

initializeClientSideCache enforces that the connection uses the RESP3 protocol before enabling client tracking, because CLIENT TRACKING invalidations are delivered via RESP3 push messages. If the negotiated/selected protocol is RESP2, a JedisException is thrown. RESP2 has no push-message channel, so client-side caching cannot work.

Solutions

  1. Set the protocol in your config: implement JedisClientConfig.getRedisProtocol() to return RedisProtocol.RESP3 (or 3).
  2. Verify the Redis server supports RESP3 (Redis >= 6.0) and the negotiated protocol is RESP3 before enabling client-side caching.
  3. If RESP2 is mandatory, do not use client-side caching; use a plain Connection and explicit key reads instead.

Example fix

// before
JedisClientConfig config = new JedisClientConfig() { /* getRedisProtocol() default -> RESP2 */ };
// after
JedisClientConfig config = new JedisClientConfig() {
  @Override public RedisProtocol getRedisProtocol() { return RedisProtocol.RESP3; }
};
Defensive patterns

Strategy: validation

Validate before calling

JedisClientConfig cfg = ...;
if (cfg.getRedisProtocol() == null || cfg.getRedisProtocol() != RedisProtocol.RESP3) {
  throw new IllegalArgumentException("Client-side caching requires RESP3: set getRedisProtocol() to RedisProtocol.RESP3");
}

Try / catch

try {
  CacheConnection conn = CacheConnection.builder(cache).clientConfig(cfg).build();
} catch (JedisException e) {
  if (e.getMessage().contains("RESP3")) {
    // switch config to RESP3 or fall back to a non-caching connection
  } else throw e;
}

Prevention

When it happens

Trigger: Building a CacheConnection (or calling initializeFromClientConfig) while the connection's protocol is RESP2 — e.g. JedisClientConfig.getRedisProtocol() returning 2 or the default protocol being RESP2; upgrading the csc wiring without also setting the protocol.

Common situations: Server is Redis < 6 (RESP2 only) or the user explicitly configured protocol 2 for compatibility; legacy configuration files carried over from pre-caching setups; middleware that hardcodes RESP2.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/redis/clients/jedis/csc/CacheConnection.java:149

    }

    // CACHE MISS !!
    cache.getStats().miss();
    T value = super.executeCommand(commandObject);
    cacheEntry = new CacheEntry<>(cacheKey, value, this);
    cache.set(cacheKey, cacheEntry);
    // this line actually provides a deep copy of cached object instance
    value = cacheEntry.getValue();
    return value;
  }

  public Cache getCache() {
    return cache;
  }

  private void initializeClientSideCache() {
    if (getRedisProtocol() != RedisProtocol.RESP3) {
      throw new JedisException("Client side caching is only supported with RESP3.");
    }
    Objects.requireNonNull(cache);
    if (!cache.compatibilityMode()) {
      RedisVersion current = new RedisVersion(version);
      RedisVersion required = new RedisVersion(MIN_REDIS_VERSION);
      if (!REDIS.equals(server) || current.compareTo(required) < 0) {
        throw new JedisException(
          String.format("Client side caching is only supported with 'Redis %s' or later.", MIN_REDIS_VERSION));
      }
    }
    addPushConsumer(new PushInvalidateConsumer(cache));
    sendCommand(Protocol.Command.CLIENT, "TRACKING", "ON");
    String reply = getStatusCodeReply();
    if (!"OK".equals(reply)) {
      throw new JedisException("Could not enable client tracking. Reply: " + reply);
    }
  }

View on GitHub (pinned to 6dac31d4c2)