netdata/netdata · error

enrichment.network_sources.{source_name}.timeout must be > 0

Error message

enrichment.network_sources.{source_name}.timeout must be > 0

What it means

Each network source's per-request timeout must be strictly positive. A timeout of 0s (or a zero Duration in code-built configs) is rejected at validation because a zero timeout would make every request fail immediately rather than give the endpoint a chance to answer. The {source_name} placeholder identifies which block is at fault.

Source

Thrown at src/crates/netflow-plugin/src/plugin_config/validation/enrichment.rs:23

use std::time::Duration;

pub(super) fn validate_enrichment(cfg: &PluginConfig) -> Result<()> {
    validate_dynamic_routing(cfg)?;

    if cfg.enrichment.classifier_cache_duration < Duration::from_secs(1) {
        anyhow::bail!("enrichment.classifier_cache_duration must be >= 1s");
    }

    for (source_name, source_cfg) in &cfg.enrichment.network_sources {
        if source_cfg.url.trim().is_empty() {
            anyhow::bail!("enrichment.network_sources.{source_name}.url must be non-empty");
        }
        let method = source_cfg.method.trim().to_ascii_uppercase();
        if method != "GET" && method != "POST" {
            anyhow::bail!("enrichment.network_sources.{source_name}.method must be GET or POST");
        }
        if source_cfg.timeout.is_zero() {
            anyhow::bail!("enrichment.network_sources.{source_name}.timeout must be > 0");
        }
        if source_cfg.interval.is_zero() {
            anyhow::bail!("enrichment.network_sources.{source_name}.interval must be > 0");
        }
        validate_network_source_tls(source_name, &source_cfg.tls)?;
        validate_network_source_transform(source_name, &source_cfg.transform)?;
    }

    for (prefix, value) in &cfg.enrichment.networks {
        validate_static_network_attributes(prefix, value)?;
    }

    Ok(())
}

fn validate_static_network_attributes(prefix: &str, value: &NetworkAttributesValue) -> Result<()> {
    let NetworkAttributesValue::Attributes(attrs) = value else {
        return Ok(());

View on GitHub (pinned to 4864de85e2)

Solutions

  1. Set a positive timeout sized to the endpoint's real latency, e.g., 30s
  2. For 'wait as long as needed', set a deliberately large value (e.g., 300s) — zero is not a valid 'unlimited'
  3. In code, ensure Duration::from_secs(n) with n >= 1

Example fix

# before
enrichment:
  network_sources:
    peers:
      timeout: 0s

# after
enrichment:
  network_sources:
    peers:
      timeout: 30s
Defensive patterns

Strategy: validation

Validate before calling

fn timeouts_ok(cfg: &PluginConfig) -> Result<()> {
    for (name, s) in &cfg.enrichment.network_sources {
        anyhow::ensure!(!s.timeout.is_zero(), "source '{name}' timeout must be > 0");
    }
    Ok(())
}

Prevention

When it happens

Trigger: enrichment.network_sources.<name>.timeout: 0s in config; timeout key present but the YAML duration parser reads it as zero (e.g., a bare '0'); constructing the config struct in Rust with Duration::ZERO.

Common situations: Attempting to express 'no timeout' with 0 (use a large value instead); typo like timeout: 0 meaning seconds; duration unit mistakes where the intended value rounds to zero.

Understand the failure class

Related errors


AI-assisted analysis of netdata/netdata@4864de85e2 (2026-08-15). Data as JSON: /api/errors/5dab37a8361ac3bd. Report an issue: GitHub.