quickwit-oss/quickwit · error

`min_connections` must be less than or equal to…

Error message

`min_connections` must be less than or equal to `max_connections`

What it means

PostgresMetastoreConfig::validate enforces that the connection pool's `min_connections` does not exceed `max_connections`. A pool whose lower bound exceeds its upper bound is contradictory and cannot be constructed by sqlx's pool.

Solutions

  1. Lower `min_connections` to be <= `max_connections`, e.g. min: 5, max: 10.
  2. Or raise `max_connections` to at least `min_connections` if a large warm pool is intended.
  3. Check env var overrides (QW_METASTORE_POSTGRES_MIN_CONNECTIONS etc.) that may silently change one of the two values.
  4. Note max_connections is a NonZeroU32 — ensure it is also > 0.

Example fix

# before
postgres:
  min_connections: 20
  max_connections: 10
# after
postgres:
  min_connections: 5
  max_connections: 10
Defensive patterns

Strategy: validation

Validate before calling

if (cfg.min_connections > cfg.max_connections || cfg.max_connections === 0) {
  throw new Error('min_connections must be <= max_connections and max_connections > 0');
}

Prevention

When it happens

Trigger: Configuring `metastore.postgres.min_connections` greater than `metastore.postgres.max_connections` (e.g. min: 20, max: 10) and running node config validation at startup.

Common situations: Tuning pool sizes independently and forgetting the relationship; raising min_connections to 'warm' the pool past an old max value; environment variable overrides raising min while config file sets max lower.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at quickwit/quickwit-config/src/metastore_config.rs:256

        if self.max_connection_lifetime.is_empty() || self.max_connection_lifetime == "0" {
            return Ok(None);
        }
        let max_connection_lifetime =
            parse_duration(&self.max_connection_lifetime).with_context(|| {
                format!(
                    "failed to parse `max_connection_lifetime` value `{}`",
                    self.max_connection_lifetime
                )
            })?;
        if max_connection_lifetime.is_zero() {
            Ok(None)
        } else {
            Ok(Some(max_connection_lifetime))
        }
    }

    pub fn validate(&self) -> anyhow::Result<()> {
        ensure!(
            self.min_connections <= self.max_connections.get(),
            "`min_connections` must be less than or equal to `max_connections`"
        );
        self.acquire_connection_timeout()?;
        self.idle_connection_timeout_opt()?;
        self.max_connection_lifetime_opt()?;
        Ok(())
    }
}

#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct FileMetastoreConfig;

impl FileMetastoreConfig {
    pub fn validate(&self) -> anyhow::Result<()> {
        Ok(())
    }

View on GitHub (pinned to a39730c5cd)