slackhq/nebula · error
error while setting up graphite sink: %s
Error message
error while setting up graphite sink: %s
What it means
When stats.type is graphite, loadStatsConfig resolves the graphite host via net.ResolveTCPAddr using the configured protocol (tcp/udp) and host. A DNS or address-format failure is wrapped as 'error while setting up graphite sink'. This fails config load, so nebula will not start until the graphite endpoint is resolvable or stats are disabled.
Source
Thrown at stats.go:350
if cfg.typ == "" || cfg.typ == "none" {
return cfg, nil
}
cfg.interval = c.GetDuration("stats.interval", 0)
if cfg.interval <= 0 {
return cfg, fmt.Errorf("stats.interval was an invalid duration: %s", c.GetString("stats.interval", ""))
}
switch cfg.typ {
case "graphite":
cfg.graphite.protocol = c.GetString("stats.protocol", "tcp")
cfg.graphite.host = c.GetString("stats.host", "")
if cfg.graphite.host == "" {
return cfg, errors.New("stats.host can not be empty")
}
addr, err := net.ResolveTCPAddr(cfg.graphite.protocol, cfg.graphite.host)
if err != nil {
return cfg, fmt.Errorf("error while setting up graphite sink: %s", err)
}
cfg.graphite.resolvedAddr = addr.String()
cfg.graphite.prefix = c.GetString("stats.prefix", "nebula")
case "prometheus":
cfg.prom.listen = c.GetString("stats.listen", "")
if cfg.prom.listen == "" {
return cfg, errors.New("stats.listen should not be empty")
}
cfg.prom.path = c.GetString("stats.path", "")
if cfg.prom.path == "" {
return cfg, errors.New("stats.path should not be empty")
}
cfg.prom.namespace = c.GetString("stats.namespace", "")
cfg.prom.subsystem = c.GetString("stats.subsystem", "")
default:
return cfg, fmt.Errorf("stats.type was not understood: %s", cfg.typ)
}
View on GitHub (pinned to dd8f660c0a)
Solutions
- Set stats.host to host:port, e.g. graphite.example.com:2003
- Verify DNS resolution from the nebula host: getent hosts <hostname>
- Use an IP address instead of a hostname if DNS is unreliable at startup
- For IPv6 literals use bracketed form: [::1]:2003
- Set stats.type: none if graphite is not actually in use
Example fix
// before stats: type: graphite host: graphite.internal // after stats: type: graphite host: graphite.internal:2003
Defensive patterns
Strategy: validation
Validate before calling
# Resolve the graphite endpoint the way nebula will, before starting
getent hosts graphite.internal
case "$(uname -s)" in Linux) ;; esac
# Go equivalent:
if _, err := net.ResolveTCPAddr("tcp", "graphite.internal:2003"); err != nil {
log.Fatalf("graphite endpoint unresolvable: %v", err)
} Try / catch
try {
loadConfig(path)
} catch (e) {
if (e.message.includes("error while setting up graphite sink")) {
console.error("stats.host must be resolvable host:port; check DNS and port syntax")
}
throw e
} Prevention
- Always include the port: host:port format (graphite.internal:2003)
- Prefer IPs or well-known DNS names verified from the nebula host at boot time
- Bracket IPv6 literals: [2001:db8::1]:2003
When it happens
Trigger: stats.host is set to an unresolvable hostname, a malformed address (missing port, bad characters), or the protocol/address combination is invalid for net.ResolveTCPAddr; DNS outage at startup.
Common situations: Typo in the graphite hostname; DNS not available in containers at boot; forgetting the port (e.g. 'graphite.internal' instead of 'graphite.internal:2003'); IPv6 literals not bracketed.
Related errors
- stats.host can not be empty
- no outside connection
- no inside interface (tun)
- stats.listen should not be empty
- stats.path should not be empty
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/a0564af832fedbb5.
Report an issue: GitHub.