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

  1. Increase service.deregisterAfter to at least 3 x healthCheckInterval.
  2. 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)