grpc/grpc-go · error
grpctransport: config %q has nil credentials bundle
Error message
grpctransport: config %q has nil credentials bundle
What it means
The Config selected by ConfigName must have a non-nil Credentials bundle (grpc_transport.go:105-106) because the gRPC dial options include grpc.WithCredentialsBundle(config.Credentials). A nil bundle would produce a broken channel, so Build rejects it upfront. The offending config name is reported.
Source
Thrown at internal/xds/clients/grpctransport/grpc_transport.go:106
// The Extension field of the ServerIdentifier must be a ServerIdentifierExtension.
func (b *Builder) Build(si clients.ServerIdentifier) (clients.Transport, error) {
if si.ServerURI == "" {
return nil, fmt.Errorf("grpctransport: ServerURI is not set in ServerIdentifier")
}
if si.Extensions == nil {
return nil, fmt.Errorf("grpctransport: Extensions is not set in ServerIdentifier")
}
sce, ok := si.Extensions.(ServerIdentifierExtension)
if !ok {
return nil, fmt.Errorf("grpctransport: Extensions field is %T, but must be %T in ServerIdentifier", si.Extensions, ServerIdentifierExtension{})
}
config, ok := b.configs[sce.ConfigName]
if !ok {
return nil, fmt.Errorf("grpctransport: unknown config name %q specified in ServerIdentifierExtension", sce.ConfigName)
}
if config.Credentials == nil {
return nil, fmt.Errorf("grpctransport: config %q has nil credentials bundle", sce.ConfigName)
}
b.mu.Lock()
defer b.mu.Unlock()
if cc, ok := b.connections[si]; ok {
if logger.V(2) {
logger.Infof("Reusing existing connection to the server for ServerIdentifier: %v", si)
}
b.refs[si]++
tr := &grpcTransport{cc: cc}
tr.cleanup = b.cleanupFunc(si, tr)
return tr, nil
}
// Create a new gRPC client/channel for the server with the provided
// credentials, server URI, and a byte codec to send and receive messages.
// Also set a static keepalive configuration that is common across gRPCView on GitHub (pinned to 03255a9237)
Solutions
- Set Config.Credentials to a valid credentials.Bundle (e.g. from tlscreds.NewBundle or credentials.NewTLS) before adding it to the map.
- If credential creation can fail, handle the error and skip registering that Config rather than registering one with nil Credentials.
- Add a precondition loop after building the configs map to assert none have nil Credentials.
Example fix
// before:
// builder := grpctransport.NewBuilder(map[string]Config{
// "default": { Credentials: nil },
// })
// after:
// bdl, closeFn, err := tlscreds.NewBundle(cfg)
// if err != nil { return err }
// builder := grpctransport.NewBuilder(map[string]Config{
// "default": { Credentials: bdl },
// }) Defensive patterns
Strategy: validation
Validate before calling
func validateConfigs(configs map[string]grpctransport.Config) error {
for name, cfg := range configs {
if cfg.Credentials == nil {
return fmt.Errorf("config %q has nil Credentials", name)
}
}
return nil
} Prevention
- Always populate Config.Credentials when building the configs map.
- Do not register a Config whose credential creation failed; skip or fail instead.
When it happens
Trigger: A Config entry was added to the NewBuilder map with Config.Credentials left nil. This can happen when the config was partially initialized or a credentials bundle failed to build but the empty Config was still registered.
Common situations: The credentials.Bundle was supposed to be created from tlscreds.NewBundle or similar but the call was omitted or its error ignored; a config was templated in without the credentials step.
Related errors
- failed to build credentials bundle from bootstrap for %q: %v
- failed to build call credentials from bootstrap for %q: %v
- xds: `channel_creds` field in server config cannot be empty:
- jwt_token_file is required in JWT call credentials config
- grpctransport: ServerURI is not set in ServerIdentifier
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/8fe0af01e084637d.
Report an issue: GitHub.