grpc/grpc-go · error
xds: failed to create a new channel for server config %v: %v
Error message
xds: failed to create a new channel for server config %v: %v
What it means
Returned when newXDSChannel returns an error inside getOrCreateChannel. newXDSChannel only fails if one of its required opts (transport, serverConfig, clientConfig, eventHandler) is nil — all of which are supplied internally by getOrCreateChannel, so in practice this indicates an internal invariant violation rather than a user config problem.
Source
Thrown at internal/xds/clients/xdsclient/xdsclient.go:308
if err != nil {
return nil, func() {}, fmt.Errorf("xds: failed to create transport for server config %v: %v", serverConfig, err)
}
state := &channelState{
parent: c,
serverConfig: serverConfig,
interestedAuthorities: make(map[*authority]bool),
}
channel, err := newXDSChannel(xdsChannelOpts{
transport: tr,
serverConfig: serverConfig,
clientConfig: c.config,
eventHandler: state,
backoff: c.backoff,
watchExpiryTimeout: c.watchExpiryTimeout,
logPrefix: clientPrefix(c),
})
if err != nil {
return nil, func() {}, fmt.Errorf("xds: failed to create a new channel for server config %v: %v", serverConfig, err)
}
state.channel = channel
c.xdsActiveChannels[*serverConfig] = state
initLocked(state)
return state.channel, c.releaseChannel(serverConfig, state, deInitLocked), nil
}
// releaseChannel is a function that is called when a reference to an xdsChannel
// needs to be released. It handles closing channels with no active references.
//
// The function takes the following parameters:
// - serverConfig: the server configuration for the xdsChannel
// - state: the state of the xdsChannel
// - deInitLocked: a function that performs any necessary cleanup for the xdsChannel
//
// The function returns another function that can be called to release the
// reference to the xdsChannel. This returned function is idempotent, meaning
// it can be called multiple times without any additional effect.View on GitHub (pinned to 03255a9237)
Solutions
- Ensure Config passed to xdsclient.New has non-nil Servers/Authorities with fully populated ServerConfig values.
- If writing custom code that touches the channel layer, never pass nil transport/serverConfig/clientConfig/eventHandler.
- Treat this as a bug to report upstream if hit through the public New/WatchResource API.
Defensive patterns
Strategy: validation
Validate before calling
// Ensure Config.Servers/Authorities entries are non-nil and populated.
func validateConfigShape(cfg xdsclient.Config) error {
for _, s := range cfg.Servers { if s == nil { return errors.New("nil ServerConfig in Servers") } }
for _, a := range cfg.Authorities {
if a == nil { return errors.New("nil Authority") }
for _, s := range a.XDSServers { if s == nil { return errors.New("nil ServerConfig in Authority") } }
}
return nil
} Prevention
- Always fully populate Config.Servers and Authorities before calling xdsclient.New.
- Treat this error as an internal bug if reached through the public API.
- Add a startup config validation pass in your bootstrap code.
When it happens
Trigger: Effectively unreachable through normal API use; would require nil serverConfig/clientConfig being passed into getOrCreateChannel, which the caller (getChannelForADS) guards against via the config construction path.
Common situations: Seen only with a malformed/nil Config (e.g. Servers or Authorities entries with nil pointers) passed to xdsclient.New, or a bug in custom code that calls getOrCreateChannel with nil fields.
Related errors
- missing server_listener_resource_name_template in the bootst
- unexpected balancer config with type: %T
- OutlierDetectionLoadBalancingConfig.interval = %s; must be >
- OutlierDetectionLoadBalancingConfig.base_ejection_time = %s;
- OutlierDetectionLoadBalancingConfig.max_ejection_time = %s;
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/0f8b1d6dad864a15.
Report an issue: GitHub.