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

  1. Set stats.host to host:port, e.g. graphite.example.com:2003
  2. Verify DNS resolution from the nebula host: getent hosts <hostname>
  3. Use an IP address instead of a hostname if DNS is unreliable at startup
  4. For IPv6 literals use bracketed form: [::1]:2003
  5. 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

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


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/a0564af832fedbb5. Report an issue: GitHub.