{"record":{"id":"f3b6a16987c45aaf","repo":"grpc/grpc-go","slug":"xds-channel-creds-field-in-server-config-cannot","errorCode":null,"errorMessage":"xds: `channel_creds` field in server config cannot be empty: %s","messagePattern":"xds: `channel_creds` field in server config cannot be empty: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/xds/bootstrap/bootstrap.go","lineNumber":403,"sourceCode":"\t\t\t\t// Skip unsupported call credential types (don't fail bootstrap).\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcallCreds, cancel, err := c.Build(cfg.Config)\n\t\t\tif err != nil {\n\t\t\t\t// Call credential validation failed - this should fail bootstrap.\n\t\t\t\treturn fmt.Errorf(\"failed to build call credentials from bootstrap for %q: %v\", cfg.Type, err)\n\t\t\t}\n\t\t\tsc.selectedCallCreds = append(sc.selectedCallCreds, callCreds)\n\t\t\tsc.extraDialOptions = append(sc.extraDialOptions, grpc.WithPerRPCCredentials(callCreds))\n\t\t\tsc.cleanups = append(sc.cleanups, cancel)\n\t\t}\n\t}\n\n\tif sc.serverURI == \"\" {\n\t\treturn fmt.Errorf(\"xds: `server_uri` field in server config cannot be empty: %s\", string(data))\n\t}\n\tif sc.credsDialOption == nil {\n\t\treturn fmt.Errorf(\"xds: `channel_creds` field in server config cannot be empty: %s\", string(data))\n\t}\n\treturn nil\n}\n\n// ServerConfigTestingOptions specifies options for creating a new ServerConfig\n// for testing purposes.\n//\n// # Testing-Only\ntype ServerConfigTestingOptions struct {\n\t// URI is the name of the server corresponding to this server config.\n\tURI string\n\t// ChannelCreds contains a list of channel credentials to use when talking\n\t// to this server. If unspecified, `insecure` credentials will be used.\n\tChannelCreds []ChannelCreds\n\t// CallCredsConfigs contains a list of call credentials to use for individual RPCs\n\t// to this server. Optional.\n\tCallCredsConfigs []CallCredsConfig\n\t// ServerFeatures represents the list of features supported by this server.","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/bootstrap/bootstrap.go#L385-L421","documentation":"Returned by ServerConfig.UnmarshalJSON (internal/xds/bootstrap/bootstrap.go:402) when no supported channel credentials could be built — i.e. credsDialOption stayed nil after iterating `channel_creds`. This means either `channel_creds` was empty, or every entry named a type not registered via bootstrap.GetChannelCredentials, or none of the registered types built successfully before the loop completed without selecting one.","triggerScenarios":"A server object has an empty `channel_creds` array, or lists only credential types the binary does not support (e.g. a custom creds type never registered), so no bundle is selected and credsDialOption remains nil.","commonSituations":"Bootstrap file with `channel_creds` omitted entirely; only unsupported types listed; a credentials plugin whose init/registration was not imported; testing without at least an \"insecure\" entry.","solutions":["Add at least one supported channel creds type, e.g. \"insecure\" or \"google_default\"","Import the package that registers any custom channel credentials so GetChannelCredentials finds it","Ensure the `channel_creds` array is non-empty in every server object"],"exampleFix":"// before\n{\"server_uri\":\"xds.example.com:443\"}\n// after\n{\"server_uri\":\"xds.example.com:443\",\"channel_creds\":[{\"type\":\"insecure\"}]}","handlingStrategy":"validation","validationCode":"var probe struct {\n    XDSServers []struct{ ChannelCreds []json.RawMessage `json:\"channel_creds\"` } `json:\"xds_servers\"`\n}\n_ = json.Unmarshal(data, &probe)\nfor i, s := range probe.XDSServers {\n    if len(s.ChannelCreds) == 0 {\n        return fmt.Errorf(\"xds_servers[%d] has empty channel_creds\", i)\n    }\n}","typeGuard":null,"tryCatchPattern":"cfg, err := bootstrap.NewConfigFromContents(data)\nif err != nil {\n    if strings.Contains(err.Error(), \"channel_creds\") {\n        log.Fatalf(\"bootstrap has no supported channel creds: %v\", err)\n    }\n}","preventionTips":["Always include at least one supported channel creds type per server","Import packages that register custom channel creds","Default to \"insecure\" in local dev, \"google_default\"/TLS in prod"],"tags":["grpc","xds","bootstrap","credentials","config","go"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}