apache/druid · error · IllegalArgumentException

socketTimeout [ ] must be greater than watchSeconds [ ]

Error message

socketTimeout [%s] must be greater than watchSeconds [%s]

What it means

Cross-field config validation: a blocking Consul watch waits up to watchSeconds; if connection.socketTimeout <= watchSeconds the HTTP read times out before the server responds, so the combination is rejected when the config is constructed.

Solutions

  1. Raise connection.socketTimeout above watch.watchSeconds (e.g. watchSeconds plus a margin).
  2. Or lower watchSeconds to fit under the configured socket timeout.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDiscoveryConfig.java:122 when the library encounters an invalid state.

Common situations: See trigger scenarios.

Understand the failure class


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/9e9c1dc8c981e982. Report an issue: GitHub.

Appendix: source

Thrown at extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDiscoveryConfig.java:122

      ServiceConfig service,
      LeaderElectionConfig leader,
      WatchConfig watch
  )
  {
    this.connection = connection == null ? new ConnectionConfig(null, null, null, null, null, null, null) : connection;
    this.auth = auth == null ? new AuthConfig(null, null, null, null) : auth;
    this.service = service;
    this.leader = leader;
    this.watch = watch == null ? new WatchConfig(null, null, null, null) : watch;

    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
          )
      );
    }

View on GitHub (pinned to 9b90983fd2)