quickwit-oss/quickwit · error

`tls.cert_poll_interval` must be greater than zero, got `{}`

Error message

`tls.cert_poll_interval` must be greater than zero, got `{}`

What it means

TlsConfig::validate requires `cert_poll_interval` to be strictly greater than zero. This interval controls how often Quickwit polls the TLS certificate files for reload; a zero interval is meaningless (either never fires or busy-loops) and is rejected.

Source

Thrown at quickwit/quickwit-config/src/node_config/mod.rs:179

    pub cert_path: String,
    pub key_path: String,
    // Path to a PEM file holding the trusted CA certificate(s). Multiple CA certificates may be
    // concatenated in the same file: all of them are trusted.
    #[serde(default)]
    pub ca_path: String,
    #[serde(default)]
    pub expected_name: Option<String>,
    #[serde(default, alias = "validate_client")]
    pub verify_client_cert: bool,
    // How often the certificate and key files are polled for changes and hot-reloaded (e.g.
    // `"5m"`). An immediate reload can also be triggered out-of-band with `SIGHUP`.
    #[serde(alias = "cert_reload_interval", default = "default_cert_poll_interval")]
    pub cert_poll_interval: HumanDuration,
}

impl TlsConfig {
    pub fn validate(&self) -> anyhow::Result<()> {
        ensure!(
            !self.cert_poll_interval.is_zero(),
            "`tls.cert_poll_interval` must be greater than zero, got `{}`",
            self.cert_poll_interval
        );
        Ok(())
    }
}

fn default_cert_poll_interval() -> HumanDuration {
    HumanDuration::try_from("5m".to_string()).expect("`5m`should be a valid human duration")
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct IndexerConfig {
    #[serde(default = "IndexerConfig::default_split_store_max_num_bytes")]
    pub split_store_max_num_bytes: ByteSize,
    #[serde(default = "IndexerConfig::default_split_store_max_num_splits")]

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Set `cert_poll_interval` to a positive duration, e.g. `1m` or `10m`.
  2. To effectively disable polling, remove the TLS cert-poll configuration rather than setting zero, or use a very large interval like `24h`.
  3. Check that the YAML value includes a unit — a bare `0` with implicit zero duration triggers this too.
  4. Remember the alias `cert_reload_interval` may be the key actually set in your file.

Example fix

# before
tls:
  cert_poll_interval: 0s
# after
tls:
  cert_poll_interval: 1m
Defensive patterns

Strategy: validation

Validate before calling

const isPositiveDuration = (d) => d !== undefined && d !== null && parseDuration(d) > 0;
if (!isPositiveDuration(cfg.grpc?.tls?.cert_poll_interval ?? '60s')) {
  throw new Error('cert_poll_interval must be > 0');
}

Prevention

When it happens

Trigger: Setting `tls.cert_poll_interval: 0s` (or `0ms`/`0` with a zero-valued HumanDuration) in a gRPC TLS config block, then validating node config at startup. Note the field also accepts the alias `cert_reload_interval`.

Common situations: Trying to 'disable' certificate polling by setting the interval to zero instead of removing the polling config; YAML value parsed as 0 due to unit omission; copy-pasted template with a zero placeholder.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/f71c94d9578f3af4. Report an issue: GitHub.