{"record":{"id":"464a8f5d1b99247e","repo":"redis/jedis","slug":"health-check-timed-out-or-failed-for-s","errorCode":null,"errorMessage":"Health check timed out or failed for %s.","messagePattern":"Health check timed out or failed for (.+?)\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/main/java/redis/clients/jedis/mcf/HealthCheckImpl.java","lineNumber":181,"sourceCode":"    log.trace(\"Health check completed for {} with status {}\", endpoint, newStatus);\n    return newStatus;\n  }\n\n  private void healthCheck() {\n    long me = System.currentTimeMillis();\n    HealthStatus update = null;\n    HealthProbeContext probeContext = new HealthProbeContext(strategy.getPolicy(),\n        strategy.getNumProbes());\n\n    while (!probeContext.isCompleted()) {\n      Future<HealthStatus> future = workers.submit(this::doHealthCheck);\n      try {\n        update = future.get(strategy.getTimeout(), TimeUnit.MILLISECONDS);\n        probeContext.record(update == HealthStatus.HEALTHY);\n      } catch (TimeoutException | ExecutionException e) {\n        future.cancel(true);\n        if (log.isWarnEnabled()) {\n          log.warn(String.format(\"Health check timed out or failed for %s.\", endpoint), e);\n        }\n        probeContext.record(false);\n      } catch (InterruptedException e) {// Health check thread was interrupted\n        future.cancel(true);\n        Thread.currentThread().interrupt(); // Restore interrupted status\n        log.warn(String.format(\"Health check interrupted for %s.\", endpoint), e);\n        // thread interrupted, stop health check process\n        return;\n      }\n      if (!probeContext.isCompleted()) {\n        try {\n          Thread.sleep(strategy.getDelayInBetweenProbes());\n        } catch (InterruptedException e) {\n          Thread.currentThread().interrupt(); // Restore interrupted status\n          log.warn(String.format(\"Health check interrupted while sleeping for %s.\", endpoint), e);\n          // thread interrupted, stop health check process\n          return;\n        }","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/mcf/HealthCheckImpl.java#L163-L199","documentation":"This is a warning logged by HealthCheckImpl.healthCheck when a scheduled health probe for an endpoint did not complete within the strategy timeout (TimeoutException) or the underlying check threw (ExecutionException). The in-flight probe future is cancelled and a failed result is recorded against the probing policy, which can eventually mark the endpoint UNHEALTHY and drive circuit-breaker failover in the multi-db (mcf) layer. It is a library-internal health-monitoring signal, not thrown to caller code.","triggerScenarios":"A single health probe submitted to the worker pool via future.get(strategy.getTimeout(), TimeUnit.MILLISECONDS) exceeds the configured HealthCheckStrategy timeout, or the strategy's doHealthCheck(endpoint) throws (e.g. JedisException from LagAwareStrategy REST calls, connection refused to the Redis Enterprise REST API).","commonSituations":"Endpoint is down or network is degraded so the health check hangs; timeout configured too low for a lag-aware REST check; Redis Enterprise REST API unreachable or slow; worker pool saturated causing slow probe execution.","solutions":["Verify the endpoint (host/port) is reachable from the client host (ping/telnet the Redis endpoint and the REST API endpoint).","Increase the health check strategy timeout (e.g. LagAwareStrategy.Config timeout) so probes under lag/network jitter complete.","Check the wrapped exception in the log to distinguish timeout vs ExecutionException; fix the root cause it reports (REST auth, TLS, DNS).","If this recurs under load, reduce health check concurrency pressure or lengthen the interval between probes."],"exampleFix":"// before\nLagAwareStrategy.Config cfg = new LagAwareStrategy.Config(restEndpoint, credsSupplier); // default/short timeout\n// after\nLagAwareStrategy.Config cfg = new LagAwareStrategy.Config.Builder(restEndpoint, credsSupplier)\n    .timeout(5000) // ms; allow slow REST-based probes to finish\n    .interval(10000)\n    .build();","handlingStrategy":"retry","validationCode":"// Pre-check endpoint reachability before relying on health-driven failover\nboolean reachable = false;\ntry (java.net.Socket s = new java.net.Socket()) {\n  s.connect(new java.net.InetSocketAddress(endpoint.getHost(), endpoint.getPort()), 3000);\n  reachable = true;\n} catch (java.io.IOException e) {\n  log.warn(\"Endpoint {} unreachable before start\", endpoint);\n}","typeGuard":null,"tryCatchPattern":"// Health checks run inside the library; guard application-level failover instead\ntry {\n  jedis.get(\"key\");\n} catch (redis.clients.jedis.exceptions.JedisConnectionException e) {\n  // provider will fail over on breaker open; retry with backoff\n  Thread.sleep(200);\n  jedis.get(\"key\");\n}","preventionTips":["Size the health check timeout larger than worst-case REST/Redis round-trip plus jitter.","Keep REST API and Redis endpoints on a stable, low-latency network path.","Monitor these warnings; alert when a high fraction of probes fail.","Use multiple probes (numProbes) with a reasonable policy so single blips don't flap status."],"tags":["health-check","timeout","multi-db","redis-enterprise","failover"],"backgroundTag":"request-timeout","analyzedSha":"6dac31d4c224fb3257c216f3985340c6f500cdcb","analyzedAt":"2026-09-08T04:55:01.204Z","contentChangedAt":"2026-09-08T04:55:01.204Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}