{"record":{"id":"dc07d6ed898d1a1c","repo":"go-kratos/kratos","slug":"invalid-discovery-config-nodes-v-region-s-zone","errorCode":null,"errorMessage":"invalid Discovery config nodes:%+v region:%s zone:%s deployEnv:%s host:%s","messagePattern":"invalid Discovery config nodes:%\\+v region:(.+?) zone:(.+?) deployEnv:(.+?) host:(.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"contrib/registry/discovery/discovery_helper.go","lineNumber":54,"sourceCode":"\t_statusUP       = \"1\"\n\t_discoveryAppID = \"infra.discovery\"\n)\n\n// Config Discovery configures.\ntype Config struct {\n\tNodes  []string\n\tRegion string\n\tZone   string\n\tEnv    string\n\tHost   string\n}\n\nfunc fixConfig(c *Config) error {\n\tif c.Host == \"\" {\n\t\tc.Host, _ = os.Hostname()\n\t}\n\tif len(c.Nodes) == 0 || c.Region == \"\" || c.Zone == \"\" || c.Env == \"\" || c.Host == \"\" {\n\t\treturn fmt.Errorf(\n\t\t\t\"invalid Discovery config nodes:%+v region:%s zone:%s deployEnv:%s host:%s\",\n\t\t\tc.Nodes,\n\t\t\tc.Region,\n\t\t\tc.Zone,\n\t\t\tc.Env,\n\t\t\tc.Host,\n\t\t)\n\t}\n\treturn nil\n}\n\n// discoveryInstance represents a server the client connects to.\ntype discoveryInstance struct {\n\tRegion   string   `json:\"region\"`           // Region is region.\n\tZone     string   `json:\"zone\"`             // Zone is IDC.\n\tEnv      string   `json:\"env\"`              // Env prod/pre/uat/fat1\n\tAppID    string   `json:\"appid\"`            // AppID is mapping service-tree appId.\n\tHostname string   `json:\"hostname\"`         // Hostname is hostname from docker","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/go-kratos/kratos/blob/668db92c2c001e9552594ba5a8aede8456af6d7e/contrib/registry/discovery/discovery_helper.go#L36-L72","documentation":"fixConfig validates the Discovery client Config at construction: Nodes, Region, Zone, and Env must be non-empty, and Host defaults to os.Hostname(); any gap aborts with this error listing the offending values. It prevents starting a client that could never resolve or register correctly.","triggerScenarios":"Constructing the discovery registry with a Config missing Nodes, Region, Zone, or Env — or with Host empty and os.Hostname() failing — so fixConfig's validation fails.","commonSituations":"Migrating configs that only set Nodes; missing REGION/ZONE/DEPLOY_ENV env vars in containers; scratch/distroless images where hostname lookup fails.","solutions":["Set every required field: Nodes plus Region, Zone, Env (and Host if the hostname cannot be resolved)","Wire the discovery config section from env vars so containers always populate it","Validate the config at startup and fail fast with a clear message"],"exampleFix":"// before\nr := discovery.New(&discovery.Config{Nodes: []string{\"127.0.0.1:7171\"}})\n\n// after\nr := discovery.New(&discovery.Config{\n    Nodes:  []string{\"127.0.0.1:7171\"},\n    Region: \"sh\",\n    Zone:   \"sh001\",\n    Env:    \"dev\",\n})","handlingStrategy":"validation","validationCode":"func validateDiscoveryConfig(c *discovery.Config) error {\n    if c.Host == \"\" {\n        c.Host, _ = os.Hostname()\n    }\n    if len(c.Nodes) == 0 || c.Region == \"\" || c.Zone == \"\" || c.Env == \"\" || c.Host == \"\" {\n        return errors.New(\"discovery config needs Nodes, Region, Zone, Env, Host\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Fail fast in main on config validation before constructing the registry","Feed the discovery section from env vars in containers","Integration-test startup with the full config in CI"],"tags":["discovery","bilibili","config","startup","validation"],"backgroundTag":null,"analyzedSha":"668db92c2c001e9552594ba5a8aede8456af6d7e","analyzedAt":"2026-08-16T02:07:20.704Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}