slackhq/nebula · error

stats.listen should not be empty

Error message

stats.listen should not be empty

What it means

When stats.type is "prometheus", nebula requires stats.listen to specify the local address:port the Prometheus HTTP endpoint binds to. An empty value is rejected at config load/reload time with this error, preventing nebula from starting with an unbindable stats endpoint.

Source

Thrown at stats.go:357

	}

	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)
	}

	return cfg, nil
}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Add `stats.listen: 127.0.0.1:8080` (or similar bind address) under the stats block
  2. Check for YAML typos/indentation so stats.listen actually lands inside the stats block
  3. Also set stats.path (required next) so the prometheus sink validates fully

Example fix

# before
stats:
  type: prometheus
  path: /metrics
# after
stats:
  type: prometheus
  listen: 127.0.0.1:8080
  path: /metrics
Defensive patterns

Strategy: validation

Validate before calling

if cfg.Stats["type"] == "prometheus" && (cfg.Stats["listen"] == nil || cfg.Stats["listen"] == "") {
    return errors.New("stats.listen must be set when stats.type is prometheus")
}

Try / catch

cfg, err := loadStatsConfig(raw)
if err != nil {
    if strings.Contains(err.Error(), "stats.listen should not be empty") {
        return fmt.Errorf("prometheus stats needs stats.listen, e.g. 127.0.0.1:8080: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Setting `stats.type: prometheus` without a `stats.listen` value during startup or SIGHUP reload; loadStatsConfig reads c.GetString("stats.listen", "") and gets an empty string.

Common situations: Switching from graphite to prometheus configs but keeping only stats.host; forgetting stats.listen entirely; YAML key typo (e.g. stat.listen) so the value silently falls back to "".

Related errors


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