redis/jedis · error · JedisValidationException
Timeout while waiting for health check result
Error message
Timeout while waiting for health check result
What it means
StatusTracker.waitForHealthStatus blocks on a CountDownLatch waiting for the health status manager to report a state change for a MultiDb failover endpoint. If the latch does not count down within healthStatusManager.getMaxWaitFor(endpoint) milliseconds, the tracker gives up and throws JedisValidationException so callers never block indefinitely on an unreachable or unhealthy endpoint.
Solutions
- Verify the target endpoint is reachable and healthy (redis-cli -h host -p port PING) before client initialization.
- Increase the configured max wait for the endpoint so slow health checks can complete.
- Check that the health check probe configuration (interval, timeout, endpoint address) matches the actual Redis instance.
- Inspect network/firewall/security-group rules between client and endpoint if the latch times out consistently.
- Catch JedisValidationException around initialization and fall back to another endpoint in the multi-db list.
Example fix
// before
MultiDbClient client = MultiDbClient.builder()
.multiDbEndpoints(endpoints) // endpoint health check max wait too small
.build();
// after
MultiDbClient client = MultiDbClient.builder()
.multiDbEndpoints(endpoints)
.connectionTimeout(5, TimeUnit.SECONDS) // give health checks room to complete
.healthCheckMaxWait(30, TimeUnit.SECONDS)
.build(); Defensive patterns
Strategy: validation
Validate before calling
if (!isEndpointReachable(endpoint)) throw new IllegalStateException("skip init: endpoint down " + endpoint);
// and ensure configured maxWait >= worst-case connect+health-check time Try / catch
try {
tracker.waitForHealthStatus(endpoint);
} catch (JedisValidationException e) {
log.warn("health check timed out for {}", endpoint, e);
failoverToAlternateEndpoint();
} Prevention
- Ping endpoints with redis-cli before configuring them as databases.
- Set health check max wait generously above network worst case.
- Monitor health check events to catch flapping endpoints early.
When it happens
Trigger: Calling waitForHealthStatus (typically via waitForInitializationPolicy during MultiDbClient/RedisClient failover-aware initialization) when the endpoint's health check never completes within the configured max wait window, e.g. the Redis node is unreachable, the health check listener never fires, or the max-wait timeout is set too low for slow networks or slow Redis startup.
Common situations: Configuring a multi-db client against a dead or firewalled Redis endpoint; setting the per-endpoint max wait (healthCheckMaxWait / getMaxWaitFor source) to a value smaller than actual connection establishment time; Redis starting slower than the client during orchestrated failovers or container startup races.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Health check timed out or failed for
- Error while checking availability
- Database can not be removed due to no healthy database…
- healthCheckStrategySupplier must not be null
- healthCheckStrategy must not be null
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/396b4c44f9c1bd54.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/mcf/StatusTracker.java:68
}
};
// Register the temporary listener
healthStatusManager.registerListener(endpoint, tempListener);
try {
// Double-check status after registering listener (race condition protection)
currentStatus = healthStatusManager.getHealthStatus(endpoint);
if (currentStatus != HealthStatus.UNKNOWN) {
return currentStatus;
}
// Wait for the health status change event
// just for safety to not block indefinitely
boolean completed = latch.await(healthStatusManager.getMaxWaitFor(endpoint),
TimeUnit.MILLISECONDS);
if (!completed) {
throw new JedisValidationException("Timeout while waiting for health check result");
}
return resultStatus.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new JedisConnectionException("Interrupted while waiting for health check result", e);
} finally {
// Clean up: unregister the temporary listener
healthStatusManager.unregisterListener(endpoint, tempListener);
}
}
}
View on GitHub (pinned to 6dac31d4c2)