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
- Set a positive timeout sized to the endpoint's real latency, e.g., 30s
- For 'wait as long as needed', set a deliberately large value (e.g., 300s) — zero is not a valid 'unlimited'
- 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
- Zero never means 'unlimited' here — use a large positive duration for slow endpoints
- Size timeout from measured endpoint latency plus margin
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- unsupported method '{}' (expected GET or POST)
- enrichment.network_sources.{source_name}.url must be non-emp
- enrichment.network_sources.{source_name}.method must be GET
- enrichment.network_sources.{source_name}.interval must be >
- unexpected HTTP status {} for {}
AI-assisted analysis of netdata/netdata@4864de85e2 (2026-08-15).
Data as JSON: /api/errors/5dab37a8361ac3bd.
Report an issue: GitHub.