grpc/grpc-go · critical
xds: failed to create transport for server config
Error message
xds: failed to create transport for server config %v: %v
What it means
The xDS client's TransportBuilder.Build returned an error when attempting to create a transport (network connection) to the xDS management server identified by the given ServerConfig. This wraps the underlying Build error with the server config for diagnostics, and means no ADS (Aggregated Discovery Service) stream can be established to that server, blocking all resource discovery.
Solutions
- Verify the xDS server URI includes host and port and is network-reachable (e.g. test with 'nc -zv host 443')
- Check TLS certificate validity and ensure ServerIdentifier.Extensions carries the correct credentials for the TransportBuilder
- Inspect the wrapped error in the log — it contains the specific Build failure (DNS resolution, TLS handshake, dial timeout, etc.)
- If using a custom TransportBuilder, ensure Build returns (non-nil Transport, nil) for a valid ServerIdentifier
- Confirm the xDS management server process is running and accepting connections
Example fix
// before — unreachable server URI, no port
config.Servers = []xdsclient.ServerConfig{{
ServerIdentifier: clients.ServerIdentifier{ServerURI: "xds-mgmt"},
}}
// after — fully qualified URI with port
config.Servers = []xdsclient.ServerConfig{{
ServerIdentifier: clients.ServerIdentifier{
ServerURI: "xds-mgmt.example.com:443",
Extensions: tlsCreds,
},
}} Defensive patterns
Strategy: validation
Validate before calling
// Validate server reachability before creating the xDS client.
for _, sc := range config.Servers {
conn, err := net.DialTimeout("tcp", sc.ServerIdentifier.ServerURI, 5*time.Second)
if err != nil {
return fmt.Errorf("xDS server %s is unreachable: %w", sc.ServerIdentifier.ServerURI, err)
}
conn.Close()
} Try / catch
client, err := xdsclient.New(config)
if err != nil {
if strings.Contains(err.Error(), "failed to create transport") {
// Transport creation failed — inspect wrapped error for network/TLS details.
// The xDS client may still be usable if other servers in the list succeed.
log.Printf("xDS transport creation failed for server: %v", err)
}
return err
} Prevention
- Validate xDS server reachability in startup/bootstrap health checks
- Use short connection timeouts in the TransportBuilder so failures surface quickly
- Monitor the grpc.xds_client.connected metric to detect transport creation failures early
- Configure multiple xDS servers for failover so a single unreachable server does not block the client
When it happens
Trigger: Called inside getOrCreateChannel (xdsclient.go:289) when no existing channel matches the server config — typically on the first resource watch or after all channels for a server have been released. The TransportBuilder.Build(serverConfig.ServerIdentifier) call returns a non-nil error (e.g. dial failure, TLS handshake error, unsupported credential type).
Common situations: xDS server URI is unresolvable or points to a wrong port; TLS certificate is expired, self-signed, or from an untrusted CA; firewall or network policy blocks the outbound connection; custom TransportBuilder returns an error due to unsupported ServerIdentifier.Extensions credential configuration; server temporarily down during initial connection attempt.
Related errors
- grpctransport: failed to create connection to server
- authority not found in the config for resource
- ErrCodeEnhanceYourCalm
- extauthz: empty grpc_service provided in config
- extauthz: missing default_value in deny_at_disable
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/1a4f8728f2d694cf.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/clients/xdsclient/xdsclient.go:291
// Use an existing channel, if one exists for this server config.
if st, ok := c.xdsActiveChannels[*serverConfig]; ok {
if c.logger.V(2) {
c.logger.Infof("Reusing an existing xdsChannel for server config %q", serverConfig)
}
initLocked(st)
return st.channel, c.releaseChannel(serverConfig, st, deInitLocked), nil
}
if c.logger.V(2) {
c.logger.Infof("Creating a new xdsChannel for server config %q", serverConfig)
}
// Create a new transport and create a new xdsChannel, and add it to the
// map of xdsChannels.
tr, err := c.transportBuilder.Build(serverConfig.ServerIdentifier)
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)
}View on GitHub (pinned to 0c51461d27)