grpc/grpc-go · error

xdsclient: no servers or authorities specified

Error message

xdsclient: no servers or authorities specified

What it means

`xdsclient.New` (xdsclient.go:103) requires the caller to specify at least one xDS server: either Config.Servers (the top-level management servers) or Config.Authorities (per-authority server lists). If both are nil the client would have nowhere to connect, so xdsclient.go:109-110 returns this error.

Source

Thrown at internal/xds/clients/xdsclient/xdsclient.go:110

	// these channels, and forwards updates from the channels to each of these
	// authorities.
	//
	// Once all references to a channel are dropped, the channel is closed.
	channelsMu        sync.Mutex
	xdsActiveChannels map[ServerConfig]*channelState // Map from server config to in-use xdsChannels.

	metricsCleanup func()
}

// New returns a new xDS Client configured with the provided config.
func New(config Config) (*XDSClient, error) {
	switch {
	case config.ResourceTypes == nil:
		return nil, errors.New("xdsclient: resource types map is nil")
	case config.TransportBuilder == nil:
		return nil, errors.New("xdsclient: transport builder is nil")
	case config.Authorities == nil && config.Servers == nil:
		return nil, errors.New("xdsclient: no servers or authorities specified")
	}
	if config.WatchExpiryTimeout == 0 {
		config.WatchExpiryTimeout = defaultWatchExpiryTimeout
	}
	client, err := newClient(&config, name)
	if err != nil {
		return nil, err
	}
	// Register this client instance as an Async Reporter.
	if client.metricsReporter != nil {
		reporter := &xdsClientMetricReporter{c: client}
		client.metricsCleanup = client.metricsReporter.RegisterAsyncReporter(reporter)
	}
	return client, nil
}

// newClient returns a new XDSClient with the given config.
func newClient(config *Config, target string) (*XDSClient, error) {

View on GitHub (pinned to 0c51461d27)

Solutions

  1. Populate Config.Servers with at least one ServerConfig, OR populate Config.Authorities with at least one named authority that itself has XDSServers.
  2. If you are loading from a bootstrap file, validate that the file contains an `xds_servers` (or `authorities`) section before constructing Config.
  3. Fail fast in your Config factory with a clearer error if both fields are empty.

Example fix

// before
cfg := xdsclient.Config{Node: node, TransportBuilder: tb, ResourceTypes: rts}
client, err := xdsclient.New(cfg) // err: no servers or authorities specified

// after
cfg := xdsclient.Config{
    Node: node, TransportBuilder: tb, ResourceTypes: rts,
    Servers: []xdsclient.ServerConfig{{
        ServerIdentifier: clients.ServerIdentifier{ServerURI: "trafficdirector.googleapis.com:443"},
    }},
}
client, err := xdsclient.New(cfg)
Defensive patterns

Strategy: validation

Validate before calling

func newXDSClientValidated(cfg xdsclient.Config) (*xdsclient.XDSClient, error) {
    hasServers := len(cfg.Servers) > 0
    hasAuthorities := false
    for _, a := range cfg.Authorities {
        if len(a.XDSServers) > 0 {
            hasAuthorities = true
            break
        }
    }
    if !hasServers && !hasAuthorities {
        return nil, errors.New("xdsclient.Config must specify at least one Server or an Authority with XDSServers")
    }
    return xdsclient.New(cfg)
}

Prevention

When it happens

Trigger: Triggered by `xdsclient.New(config)` where both `config.Servers == nil` and `config.Authorities == nil`. The check at line 109 short-circuits: the OR condition is only satisfied if at least one is non-nil.

Common situations: Loading a bootstrap that contains no server entries; mis-parsing the bootstrap so the server list ends up empty; building a Config in tests with only Node/TransportBuilder set; an authority map that exists but is empty in a way that decodes to nil.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/7c817b8ecb252cdf. Report an issue: GitHub.