grpc/grpc-go · error
xds: `channel_creds` field in server config cannot be empty
Error message
xds: `channel_creds` field in server config cannot be empty: %s
What it means
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.
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.
Example fix
// before (no supported creds)
{"server_uri":"td:443","channel_creds":[{"type":"mtls"}]}
// after
{"server_uri":"td:443","channel_creds":[{"type":"google_default"}]} Defensive patterns
Strategy: validation
Validate before calling
// Ensure each server declares at least one supported channel creds type.
var supportedChannelCreds = map[string]bool{"google_default": true, "insecure": true, "tlscreds_mtls": true}
func hasSupportedChannelCreds(servers []map[string]any) error {
for i, s := range servers {
ccs, _ := s["channel_creds"].([]any)
ok := false
for _, c := range ccs {
cm, _ := c.(map[string]any)
if supportedChannelCreds[fmt.Sprint(cm["type"])] {
ok = true
break
}
}
if !ok {
return fmt.Errorf("servers[%d]: no supported channel_creds", i)
}
}
return nil
} Try / catch
if _, err := bootstrap.NewConfigFromContents(data); err != nil {
if strings.Contains(err.Error(), "channel_creds") {
// add a supported channel_creds type to the failing server.
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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'.
Related errors
- failed to build credentials bundle from bootstrap for
- failed to build call credentials from bootstrap for
- missing server_listener_resource_name_template in the…
- xds: config parsing for certificate provider plugin
- xds: error normalizing JSON bootstrap configuration
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/f3b6a16987c45aaf.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/bootstrap/bootstrap.go:403
// Skip unsupported call credential types (don't fail bootstrap).
continue
}
callCreds, cancel, err := c.Build(cfg.Config)
if err != nil {
// Call credential validation failed - this should fail bootstrap.
return fmt.Errorf("failed to build call credentials from bootstrap for %q: %v", cfg.Type, err)
}
sc.selectedCallCreds = append(sc.selectedCallCreds, callCreds)
sc.extraDialOptions = append(sc.extraDialOptions, grpc.WithPerRPCCredentials(callCreds))
sc.cleanups = append(sc.cleanups, cancel)
}
}
if sc.serverURI == "" {
return fmt.Errorf("xds: `server_uri` field in server config cannot be empty: %s", string(data))
}
if sc.credsDialOption == nil {
return fmt.Errorf("xds: `channel_creds` field in server config cannot be empty: %s", string(data))
}
return nil
}
// ServerConfigTestingOptions specifies options for creating a new ServerConfig
// for testing purposes.
//
// # Testing-Only
type ServerConfigTestingOptions struct {
// URI is the name of the server corresponding to this server config.
URI string
// ChannelCreds contains a list of channel credentials to use when talking
// to this server. If unspecified, `insecure` credentials will be used.
ChannelCreds []ChannelCreds
// CallCredsConfigs contains a list of call credentials to use for individual RPCs
// to this server. Optional.
CallCredsConfigs []CallCredsConfig
// ServerFeatures represents the list of features supported by this server.View on GitHub (pinned to 0c51461d27)