grpc/grpc-go · error

xdsclient: serverConfig is nil

Error message

xdsclient: serverConfig is nil

What it means

Inside `newXDSChannel` (channel.go:79), after the transport check, the next mandatory field is `serverConfig` (*ServerConfig) describing which xDS management server to connect to. The channel needs the server's ServerIdentifier (address, etc.) and features to dial the right destination, so a nil value is rejected at channel.go:83-84.

Source

Thrown at internal/xds/clients/xdsclient/channel.go:84

type xdsChannelOpts struct {
	transport          clients.Transport       // Takes ownership of this transport.
	serverConfig       *ServerConfig           // Configuration of the server to connect to.
	clientConfig       *Config                 // Complete xDS client configuration, used to decode resources.
	eventHandler       xdsChannelEventHandler  // Callbacks for ADS stream events.
	backoff            func(int) time.Duration // Backoff function to use for stream retries. Defaults to exponential backoff, if unset.
	watchExpiryTimeout time.Duration           // Timeout for ADS resource watch expiry.
	logPrefix          string                  // Prefix to use for logging.
}

// newXDSChannel creates a new xdsChannel instance with the provided options.
// It performs basic validation on the provided options and initializes the
// xdsChannel with the necessary components.
func newXDSChannel(opts xdsChannelOpts) (*xdsChannel, error) {
	switch {
	case opts.transport == nil:
		return nil, errors.New("xdsclient: transport is nil")
	case opts.serverConfig == nil:
		return nil, errors.New("xdsclient: serverConfig is nil")
	case opts.clientConfig == nil:
		return nil, errors.New("xdsclient: clientConfig is nil")
	case opts.eventHandler == nil:
		return nil, errors.New("xdsclient: eventHandler is nil")
	}

	xc := &xdsChannel{
		transport:    opts.transport,
		serverConfig: opts.serverConfig,
		clientConfig: opts.clientConfig,
		eventHandler: opts.eventHandler,
		closed:       syncutil.NewEvent(),
	}

	l := grpclog.Component("xds")
	logPrefix := opts.logPrefix + fmt.Sprintf("[xds-channel %p] ", xc)
	xc.logger = igrpclog.NewPrefixLogger(l, logPrefix)

View on GitHub (pinned to 0c51461d27)

Solutions

  1. Verify the Config.Authorities and Config.Servers entries used to resolve the serverConfig are non-empty and well-formed.
  2. If you author a custom ResourceType or authority resolution path, ensure it always yields a non-nil *ServerConfig.
  3. Add a sanity check that logs the serverConfig before calling newXDSChannel so the source of the nil is obvious.

Example fix

// before
opts := xdsChannelOpts{transport: t, clientConfig: cc, eventHandler: h}
xc, err := newXDSChannel(opts) // err: serverConfig is nil

// after
sc, ok := resolveServerConfig(authorityName)
if !ok || sc == nil { return fmt.Errorf("no server config for authority %q", authorityName) }
opts := xdsChannelOpts{transport: t, serverConfig: sc, clientConfig: cc, eventHandler: h}
xc, err := newXDSChannel(opts)
Defensive patterns

Strategy: validation

Validate before calling

func resolveAndValidateServerConfig(authorities map[string]xdsclient.Authority, authorityName string) (*xdsclient.ServerConfig, error) {
    a, ok := authorities[authorityName]
    if !ok {
        return nil, fmt.Errorf("authority %q not configured", authorityName)
    }
    if len(a.XDSServers) == 0 || a.XDSServers[0].ServerIdentifier.ServerURI == "" {
        return nil, fmt.Errorf("authority %q has no xDS servers", authorityName)
    }
    return &a.XDSServers[0], nil
}

Prevention

When it happens

Trigger: Triggered when `newXDSChannel` is called with `opts.serverConfig == nil` while building a channel for an authority. This is an internal contract violation: the caller (the XDSClient) is expected to resolve a server config before requesting a channel.

Common situations: An xDS authority/configuration that resolves to no servers (e.g. an authority name in the Config map but with empty XDSServers); a custom resource-type implementation that bypasses the normal resolution; misconstructed Config.Authorities map.

Related errors


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