{"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":"error","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/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/bootstrap/bootstrap.go#L385-L421","documentation":"Returned when no supported channel credentials type could be built for a server, leaving sc.credsDialOption nil. Either channel_creds is empty, or none of the listed credential type names are registered/supported by this client, so the bootstrap is rejected.","triggerScenarios":"Triggered at bootstrap.go:403 after the loop over server.ChannelCreds at bootstrap.go:360 finds no registered credential plugin (bootstrap.GetChannelCredentials returns nil for every entry) or none that builds successfully without erroring first.","commonSituations":"channel_creds array omitted; only unsupported type names listed (e.g. 'fake'); typo in a supported name; the supported names are 'google_default' or 'insecure' or a registered tls plugin such as 'tlscreds_mtls'.","solutions":["Ensure the server object has a non-empty channel_creds array.","Use a supported type, e.g. {\"type\":\"google_default\"} for production or {\"type\":\"insecure\"} for local testing.","If using a custom channel creds plugin, register it via bootstrap.RegisterChannelCredentials before GetConfiguration.","Check spelling of the type name against the registered plugin."],"exampleFix":"// before (no supported creds)\n{\"server_uri\":\"td:443\",\"channel_creds\":[{\"type\":\"mtls\"}]}\n\n// after\n{\"server_uri\":\"td:443\",\"channel_creds\":[{\"type\":\"google_default\"}]}","handlingStrategy":"validation","validationCode":"// Ensure each server declares at least one supported channel creds type.\nvar supportedChannelCreds = map[string]bool{\"google_default\": true, \"insecure\": true, \"tlscreds_mtls\": true}\n\nfunc hasSupportedChannelCreds(servers []map[string]any) error {\n    for i, s := range servers {\n        ccs, _ := s[\"channel_creds\"].([]any)\n        ok := false\n        for _, c := range ccs {\n            cm, _ := c.(map[string]any)\n            if supportedChannelCreds[fmt.Sprint(cm[\"type\"])] {\n                ok = true\n                break\n            }\n        }\n        if !ok {\n            return fmt.Errorf(\"servers[%d]: no supported channel_creds\", i)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if _, err := bootstrap.NewConfigFromContents(data); err != nil {\n    if strings.Contains(err.Error(), \"channel_creds\") {\n        // add a supported channel_creds type to the failing server.\n    }\n}","preventionTips":["Default to google_default (prod) or insecure (local) to avoid this entirely.","Register custom channel creds plugins before GetConfiguration.","Lint channel_creds type names against the registered set."],"tags":["grpc","xds","bootstrap","credentials","channel-creds","config","go"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}