{"record":{"id":"c5602a3d03ceaa2f","repo":"slackhq/nebula","slug":"stats-host-can-not-be-empty","errorCode":null,"errorMessage":"stats.host can not be empty","messagePattern":"stats\\.host can not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"stats.go","lineNumber":346,"sourceCode":"func loadStatsConfig(c *config.C) (statsConfig, error) {\n\tcfg := statsConfig{\n\t\ttyp: c.GetString(\"stats.type\", \"\"),\n\t}\n\tif cfg.typ == \"\" || cfg.typ == \"none\" {\n\t\treturn cfg, nil\n\t}\n\n\tcfg.interval = c.GetDuration(\"stats.interval\", 0)\n\tif cfg.interval <= 0 {\n\t\treturn cfg, fmt.Errorf(\"stats.interval was an invalid duration: %s\", c.GetString(\"stats.interval\", \"\"))\n\t}\n\n\tswitch cfg.typ {\n\tcase \"graphite\":\n\t\tcfg.graphite.protocol = c.GetString(\"stats.protocol\", \"tcp\")\n\t\tcfg.graphite.host = c.GetString(\"stats.host\", \"\")\n\t\tif cfg.graphite.host == \"\" {\n\t\t\treturn cfg, errors.New(\"stats.host can not be empty\")\n\t\t}\n\t\taddr, err := net.ResolveTCPAddr(cfg.graphite.protocol, cfg.graphite.host)\n\t\tif err != nil {\n\t\t\treturn cfg, fmt.Errorf(\"error while setting up graphite sink: %s\", err)\n\t\t}\n\t\tcfg.graphite.resolvedAddr = addr.String()\n\t\tcfg.graphite.prefix = c.GetString(\"stats.prefix\", \"nebula\")\n\tcase \"prometheus\":\n\t\tcfg.prom.listen = c.GetString(\"stats.listen\", \"\")\n\t\tif cfg.prom.listen == \"\" {\n\t\t\treturn cfg, errors.New(\"stats.listen should not be empty\")\n\t\t}\n\t\tcfg.prom.path = c.GetString(\"stats.path\", \"\")\n\t\tif cfg.prom.path == \"\" {\n\t\t\treturn cfg, errors.New(\"stats.path should not be empty\")\n\t\t}\n\t\tcfg.prom.namespace = c.GetString(\"stats.namespace\", \"\")\n\t\tcfg.prom.subsystem = c.GetString(\"stats.subsystem\", \"\")","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/stats.go#L328-L364","documentation":"Nebula's loadStatsConfig validates the graphite stats sink configuration. When stats.type is \"graphite\", stats.host must be set to a resolvable host:port; if the host string is empty the config is rejected with this error and nebula refuses to (re)load the configuration.","triggerScenarios":"Setting `stats.type: graphite` in the nebula config without defining `stats.host` (or leaving it empty), during initial start or a config reload triggered via SIGHUP.","commonSituations":"Copy-pasting a stats config block and omitting stats.host; switching stats.type to graphite while only prometheus keys (stats.listen/stats.path) are present; malformed YAML indentation nesting stats.host outside the stats block.","solutions":["Add a `stats.host` key with a host:port value (e.g. \"127.0.0.1:2003\") under the stats block","Verify YAML indentation places stats.host inside stats alongside stats.type","If you intend prometheus instead, set stats.type: prometheus and configure stats.listen/stats.path"],"exampleFix":"# before\nstats:\n  type: graphite\n  protocol: tcp\n# after\nstats:\n  type: graphite\n  protocol: tcp\n  host: 127.0.0.1:2003\n  prefix: nebula","handlingStrategy":"validation","validationCode":"host := cfg.Stats[\"host\"]\nif cfg.Stats[\"type\"] == \"graphite\" && (host == nil || host == \"\") {\n    return errors.New(\"stats.host must be set when stats.type is graphite\")\n}","typeGuard":null,"tryCatchPattern":"cfg, err := loadStatsConfig(raw)\nif err != nil {\n    if strings.Contains(err.Error(), \"stats.host can not be empty\") {\n        return fmt.Errorf(\"stats config: set stats.host like 127.0.0.1:2003: %w\", err)\n    }\n    return err\n}","preventionTips":["Always set stats.host whenever stats.type is graphite","Validate the nebula config with a linter before SIGHUP reload","Keep graphite and prometheus key sets separated per profile","Check YAML indentation places stats.host inside the stats block"],"tags":["nebula","config","graphite","stats","validation"],"backgroundTag":"missing-config-key","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}