grpc/grpc-go · error

xds: failed to create transport for server config %v: %v

Error message

xds: failed to create transport for server config %v: %v

What it means

Returned (propagated up through getOrCreateChannel and getChannelForADS) when c.transportBuilder.Build(serverConfig.ServerIdentifier) fails while creating a new xDS channel for an authority. It is a hard setup error: the channel cannot be created, so the ADS watch fails to be served.

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 03255a9237)

Solutions

  1. Inspect the wrapped %v: dial/DNS errors point to connectivity, auth errors to credentials, config errors to the builder.
  2. Validate every ServerConfig.ServerIdentifier in Config.Servers and Config.Authorities before building the XDSClient.
  3. Ensure the TransportBuilder is constructed with the right credentials for each server.
  4. Confirm the management server is reachable from the client network.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-build and close a transport to verify each server config builds.
func validateServerConfigs(b clients.TransportBuilder, cfg xdsclient.Config) error {
    check := func(si clients.ServerIdentifier) error {
        tr, err := b.Build(si); if err != nil { return err }
        tr.Close(); return nil
    }
    for _, s := range cfg.Servers { if err := check(s.ServerIdentifier); err != nil { return err } }
    for _, a := range cfg.Authorities {
        for _, s := range a.XDSServers { if err := check(s.ServerIdentifier); err != nil { return err } }
    }
    return nil
}

Try / catch

// getChannelForADS returns the error through WatchResource's ambient path;
// surface it from the watcher's AmbientError/ResourceError callback.
func (w *myWatcher) AmbientError(err error, done func()) {
    defer done()
    logger.Errorf("xDS channel setup failed: %v", err)
}

Prevention

When it happens

Trigger: An authority's ServerConfig references a ServerIdentifier that the TransportBuilder cannot build a transport for — bad URI, unresolvable DNS, rejected credentials, or a custom builder error. First subscription for that server config triggers it.

Common situations: Wrong server URI or port in a ServerConfig inside Config.Authorities, missing credentials for a TLS server, a custom TransportBuilder rejecting the identifier, or an unreachable/typo'd management server host.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/1a4f8728f2d694cf. Report an issue: GitHub.