redis/jedis · error · JedisException

Client side caching is only supported with 'Redis 7.4' or…

Error message

Client side caching is only supported with 'Redis 7.4' or later.

What it means

Unless the Cache was explicitly put in compatibility mode, initializeClientSideCache verifies the server advertises itself as 'redis' with version >= 7.4 (MIN_REDIS_VERSION) before issuing CLIENT TRACKING ON. Older servers or non-Redis endpoints fail this check and a JedisException is thrown. Newer tracking semantics (e.g. broadcast/format behavior) rely on 7.4+ features.

Solutions

  1. Upgrade the Redis server to 7.4 or later.
  2. If you accept degraded semantics, enable compatibility mode on your cache (cache.setCacheable/CacheConfig with compatibilityMode true, e.g. DefaultCache.setCompatibilityMode(true)) so this check is skipped.
  3. Pin environment versions so dev/prod both run >= 7.4; check INFO server during rollout.
  4. For non-'redis' server forks/proxies, either use compatibility mode or switch to genuine Redis for csc workloads.

Example fix

// before
Cache cache = CacheFactory.getCache(config); // compatibilityMode = false, server = Redis 6.2
// after
cache.setCompatibilityMode(true); // or upgrade Redis to >= 7.4
Defensive patterns

Strategy: validation

Validate before calling

// check server before enabling csc
Map<String, String> info = jedis.info("server");
String version = info.get("redis_version");
if (compareVersion(version, "7.4") < 0 && !cache.compatibilityMode()) {
  cache.setCompatibilityMode(true); // or upgrade the server
}

Try / catch

try {
  CacheConnection conn = CacheConnection.builder(cache).clientConfig(cfg).build();
} catch (JedisException e) {
  if (e.getMessage().contains("or later")) {
    cache.setCompatibilityMode(true); // retry in compatibility mode
  } else throw e;
}

Prevention

When it happens

Trigger: Connecting a CacheConnection (directly or via initializeFromClientConfig) to a Redis server reporting INFO server version < 7.4, or to a server whose 'server' field is not 'redis' (e.g. keydb, dragonfly, memtier proxies) while cache.compatibilityMode() is false.

Common situations: Running against an older Redis fleet after adding client-side caching; using Redis-compatible servers/proxies that report a different 'server' name or downlevel version; version drift between environments (dev on 7.4, prod on 6.x).

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/711913e447524585. Report an issue: GitHub.

Appendix: source

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

    // 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);
    }
  }

  @SuppressWarnings("rawtypes")
  private CacheEntry validateEntry(CacheEntry cacheEntry) {
    CacheConnection cacheOwner = cacheEntry.getConnection();
    if (cacheOwner == null || cacheOwner.isBroken() || !cacheOwner.isConnected()) {
      cache.delete(cacheEntry.getCacheKey());
      return null;
    } else {

View on GitHub (pinned to 6dac31d4c2)