{"record":{"id":"1cd3f4cf05d966e9","repo":"apache/druid","slug":"exception-pulling-items-from-cache","errorCode":null,"errorMessage":"Exception pulling items from cache","messagePattern":"Exception pulling items from cache","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"extensions-contrib/redis-cache/src/main/java/org/apache/druid/client/cache/AbstractRedisCache.java","lineNumber":108,"sourceCode":"\n  @Override\n  public Map<NamedKey, byte[]> getBulk(Iterable<NamedKey> keys)\n  {\n    totalRequestCount.incrementAndGet();\n    try {\n      Pair<Integer, Map<NamedKey, byte[]>> results = this.mgetFromRedis(keys);\n\n      hitCount.addAndGet(results.rhs.size());\n      missCount.addAndGet(results.lhs - results.rhs.size());\n      return results.rhs;\n    }\n    catch (JedisException e) {\n      if (e.getMessage().contains(\"Read timed out\")) {\n        timeoutCount.incrementAndGet();\n      } else {\n        errorCount.incrementAndGet();\n      }\n      log.warn(e, \"Exception pulling items from cache\");\n      return Collections.emptyMap();\n    }\n  }\n\n  @Override\n  public void close(String namespace)\n  {\n    // no resources to cleanup\n  }\n\n  @Override\n  @LifecycleStop\n  public void close()\n  {\n    cleanup();\n  }\n\n  @Override","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/redis-cache/src/main/java/org/apache/druid/client/cache/AbstractRedisCache.java#L90-L126","documentation":"AbstractRedisCache.getBulk() catches JedisException when fetching multiple values (MGET/pipeline) from Redis and returns an empty map, logging this warning. A message containing 'Read timed out' increments timeoutCount; anything else increments errorCount. Like get(), failures degrade to a cache miss rather than failing the operation.","triggerScenarios":"Calling cache.getBulk(keys) when the Redis connection fails or a pipelined/multi-key read times out.","commonSituations":"Bulk fetch of many segment keys over a slow network to Redis; Redis load shedding during heavy load; connection pool exhausted; Redis cluster resharding mid-read.","solutions":["Verify Redis reachability and increase the read timeout in the redis cache config","Reduce bulk sizes or Redis network latency (same-DC deployment)","Check Redis server health (latency, maxmemory, slowlog)","Watch errorCount vs timeoutCount metrics to distinguish connectivity errors from slow reads","Accept empty results gracefully: getBulk always returns an empty map on failure by design"],"exampleFix":"// before\nMap<NamedKey, byte[]> values = cache.getBulk(keys); // assume all present\n// after: handle partial/empty results\nMap<NamedKey, byte[]> values = cache.getBulk(keys);\nList<NamedKey> missing = keys.stream().filter(k -> !values.containsKey(k)).collect(Collectors.toList());","handlingStrategy":"fallback","validationCode":"try (Jedis j = new Jedis(host, port, 2000)) { j.ping(); }","typeGuard":null,"tryCatchPattern":"Map<NamedKey, byte[]> vals = cache.getBulk(keys);\n// always check per-key presence; empty map is returned on any Redis failure\nList<NamedKey> missing = keys.stream().filter(k -> !vals.containsKey(k)).collect(Collectors.toList());","preventionTips":["Handle empty/partial bulk results as a normal path","Increase read timeout for large bulk fetches","Keep Redis latency low (same DC, adequate resources)","Track errorCount metric for connectivity issues"],"tags":["redis","cache","network","bulk-read"],"backgroundTag":"request-timeout","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}