apache/druid · error · IllegalArgumentException

watchSeconds [ ] must be at least 1 second to avoid…

Error message

watchSeconds [%s] must be at least 1 second to avoid non-blocking query loops

What it means

WatchConfig validation: watchSeconds must be at least 1 second; a zero-second watch degenerates into a tight non-blocking polling loop against the Consul API, so such values are rejected when the config is created.

Solutions

  1. Set watch.watchSeconds to at least 1 second (typical blocking-query values are 30-300s).
  2. Remove the property to use the default watch duration.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDiscoveryConfig.java:707 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/90143eca2cd82377. Report an issue: GitHub.

Appendix: source

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

    private static final long DEFAULT_CIRCUIT_BREAKER_SLEEP_MS = 120_000; // 2 minutes

    private final Duration watchSeconds;
    private final long maxWatchRetries;
    private final Duration watchRetryDelay;
    private final Duration circuitBreakerSleep;

    @JsonCreator
    public WatchConfig(
        @JsonProperty("watchSeconds") @Nullable Duration watchSeconds,
        @JsonProperty("maxWatchRetries") @Nullable Long maxWatchRetries,
        @JsonProperty("watchRetryDelay") @Nullable Duration watchRetryDelay,
        @JsonProperty("circuitBreakerSleep") @Nullable Duration circuitBreakerSleep
    )
    {
      this.watchSeconds = validatePositive(watchSeconds, DEFAULT_WATCH_TIMEOUT_MS, "watchSeconds");
      // Consul blocking queries use seconds; sub-second values truncate to 0 causing tight loops
      if (this.watchSeconds.getStandardSeconds() < 1) {
        throw new IAE(
            StringUtils.format(
                "watchSeconds [%s] must be at least 1 second to avoid non-blocking query loops",
                this.watchSeconds
            )
        );
      }
      this.maxWatchRetries = (maxWatchRetries == null || maxWatchRetries <= 0) ? Long.MAX_VALUE : maxWatchRetries;
      this.watchRetryDelay = validateNonNegative(watchRetryDelay, DEFAULT_WATCH_RETRY_DELAY_MS, "watchRetryDelay");
      this.circuitBreakerSleep = validatePositive(circuitBreakerSleep, DEFAULT_CIRCUIT_BREAKER_SLEEP_MS, "circuitBreakerSleep");
    }

    @JsonProperty
    public Duration getWatchSeconds()
    {
      return watchSeconds;
    }

    @JsonProperty

View on GitHub (pinned to 9b90983fd2)