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
- Add `stats.listen: 127.0.0.1:8080` (or similar bind address) under the stats block
- Check for YAML typos/indentation so stats.listen actually lands inside the stats block
- 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
- Always set stats.listen when using stats.type: prometheus
- Bind to 127.0.0.1 unless exposing metrics deliberately
- Validate config before reload to avoid dropping a running tunnel
- Watch for key typos that silently fall back to the empty default
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
- stats.path should not be empty
- stats.host can not be empty
- stats.interval was an invalid duration: %s
- stats.type was not understood: %s
- config `%s` has invalid type: %T
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/0491b244bfb11b6e.
Report an issue: GitHub.