quickwit-oss/quickwit · error

`rest.max_connection_age_grace` requires…

Error message

`rest.max_connection_age_grace` requires `rest.max_connection_age` to be set

What it means

The REST server's `max_connection_age_grace` is a grace period applied after `max_connection_age` cuts connections; it is meaningless without a base age. `build_and_validate` rejects a REST config where grace is set but `max_connection_age` is not, ensuring the connection-lifecycle settings stay coherent.

Solutions

  1. Also set `rest.max_connection_age` alongside `rest.max_connection_age_grace` in the REST config.
  2. Or remove `max_connection_age_grace` if connection aging is not desired.
  3. Verify env vars resolve both keys (a missing max_connection_age env var leaves it None even if YAML looks correct).

Example fix

// before (quickwit.yaml)
rest:
  max_connection_age_grace: 30s

// after (quickwit.yaml)
rest:
  max_connection_age: 60s
  max_connection_age_grace: 30s
Defensive patterns

Strategy: validation

Validate before calling

if cfg.rest.max_connection_age_grace.is_some() && cfg.rest.max_connection_age.is_none() {
    return Err("rest.max_connection_age_grace set without rest.max_connection_age");
}

Type guard

fn connection_aging_coherent(rest: &RestConfigDto) -> bool {
    rest.max_connection_age_grace.is_none() || rest.max_connection_age.is_some()
}

Try / catch

match load_node_config(path) {
    Err(e) if e.to_string().contains("max_connection_age_grace") =>
        bail!("also set rest.max_connection_age (grace requires a base age)"),
    other => other,
}

Prevention

When it happens

Trigger: Setting `rest.max_connection_age_grace` (or its env-resolved equivalent) without also setting `rest.max_connection_age` when loading the node config via build_and_validate.

Common situations: Operators tune only the grace value copied from a gRPC example; partial config merging drops max_connection_age while keeping grace; typos like nesting grace under a different key so max_connection_age resolves to None.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at quickwit/quickwit-config/src/node_config/serialize.rs:578

}

impl RestConfigBuilder {
    fn build_and_validate(
        self,
        listen_ip: IpAddr,
        env_vars: &HashMap<String, String>,
    ) -> anyhow::Result<RestConfig> {
        let listen_port_from_config_or_default =
            self.listen_port.unwrap_or(default_rest_listen_port());
        let listen_port = ConfigValue::<u16, QW_REST_LISTEN_PORT>::with_default(
            listen_port_from_config_or_default,
        )
        .resolve(env_vars)?;

        if let Some(tls_config) = &self.tls_config {
            tls_config.validate()?;
        }
        ensure!(
            !(self.max_connection_age_grace.is_some() && self.max_connection_age.is_none()),
            "`rest.max_connection_age_grace` requires `rest.max_connection_age` to be set"
        );
        let rest_config = RestConfig {
            listen_addr: SocketAddr::new(listen_ip, listen_port),
            cors_allow_origins: self.cors_allow_origins,
            extra_headers: self.extra_headers,
            tls_config: self.tls_config,
            max_connection_age: self.max_connection_age,
            max_connection_age_grace: self.max_connection_age_grace,
        };
        Ok(rest_config)
    }
}

#[derive(Debug, Deserialize, PartialEq, Default)]
#[serde(deny_unknown_fields)]
struct HealthConfigBuilder {

View on GitHub (pinned to a39730c5cd)