apache/druid · error · IllegalArgumentException
deregisterAfter (%ds) must be >= service TTL (%ds = 3 ×…
Error message
deregisterAfter (%ds) must be >= service TTL (%ds = 3 × healthCheckInterval)
What it means
Cross-field config validation: Consul deregisters a service after deregisterWithoutHealthCheck; the value must be >= the derived service TTL (3 x healthCheckInterval, minimum 30s), otherwise healthy services would be deregistered between checks.
Solutions
- Increase service.deregisterAfter to at least 3 x healthCheckInterval.
- Shorten healthCheckInterval so the derived TTL fits under deregisterAfter.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDiscoveryConfig.java:133 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/80a991344c86051c.
Report an issue: GitHub.
Appendix: source
Thrown at extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDiscoveryConfig.java:133
validateCrossFieldConstraints();
}
private void validateCrossFieldConstraints()
{
// Socket timeout must exceed watch timeout to avoid premature disconnects
if (connection.getSocketTimeout().compareTo(watch.getWatchSeconds()) <= 0) {
throw new IAE(
StringUtils.format(
"socketTimeout [%s] must be greater than watchSeconds [%s]",
connection.getSocketTimeout(),
watch.getWatchSeconds()
)
);
}
long serviceTtlSeconds = Math.max(30, service.getHealthCheckInterval().getStandardSeconds() * 3);
if (service.getDeregisterAfter().getStandardSeconds() < serviceTtlSeconds) {
throw new IAE(
StringUtils.format(
"deregisterAfter (%ds) must be >= service TTL (%ds = 3 × healthCheckInterval)",
service.getDeregisterAfter().getStandardSeconds(),
serviceTtlSeconds
)
);
}
// Large watchSeconds relative to session TTL can delay failure detection
if (watch.getWatchSeconds().getStandardSeconds() > leader.getLeaderSessionTtl().getStandardSeconds() * 2) {
LOGGER.warn(
"watchSeconds (%ds) is much larger than leaderSessionTtl (%ds): delayed failure detection possible",
watch.getWatchSeconds().getStandardSeconds(),
leader.getLeaderSessionTtl().getStandardSeconds()
);
}
}
View on GitHub (pinned to 9b90983fd2)