grpc/grpc-go · critical
missing server_listener_resource_name_template in the…
Error message
missing server_listener_resource_name_template in the bootstrap configuration
What it means
Returned by xds.NewGRPCServer (xds/server.go:111) when the xDS client's bootstrap configuration has an empty server_listener_resource_name_template. On the server side this template is mandatory because gRPC uses it to derive the Listener resource name it subscribes to (e.g. 'grpc/server?<ip:port>'); without it the server cannot know which xDS Listener resource to watch, so construction fails fast. NewGRPCServer also closes the freshly created xDS client before returning the error.
Solutions
- Add a non-empty server_listener_resource_name_template to the bootstrap JSON, e.g. "grpc/server?%s" (the %s is replaced with the server's IP:port).
- Point GRPC_XDS_BOOTSTRAP at a bootstrap file that includes the xds_servers entry AND server_listener_resource_name_template.
- Regenerate the bootstrap from your control plane / bootstrap generator with server-side fields enabled.
- Verify after construction by reading xdsClient.BootstrapConfig().ServerListenerResourceNameTemplate() before calling Serve.
Example fix
// before (bootstrap.json)
{
"xds_servers": [{ "server_config": {...} }]
}
// -> NewGRPCServer fails: missing server_listener_resource_name_template
// after
{
"xds_servers": [{ "server_config": {...} }],
"server_listener_resource_name_template": "grpc/server?%s"
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the bootstrap has the server template before constructing the xDS server.
import "google.golang.org/grpc/xds"
if os.Getenv("GRPC_XDS_BOOTSTRAP") == "" && os.Getenv("GRPC_XDS_BOOTSTRAP_FILE_CONTENT") == "" {
log.Fatal("xDS bootstrap not configured")
}
// Optionally parse the bootstrap JSON and assert server_listener_resource_name_template != "". Try / catch
gs, err := xds.NewGRPCServer(opts...)
if err != nil {
if strings.Contains(err.Error(), "server_listener_resource_name_template") {
// fix bootstrap JSON and retry; do not proceed to Serve
}
} Prevention
- Always include a non-empty server_listener_resource_name_template in the bootstrap used for servers.
- Keep separate bootstrap files for client-only vs server workloads, or ensure the shared one has both fields.
- Regenerate bootstrap from your control plane with server fields enabled.
When it happens
Trigger: Calling xds.NewGRPCServer(opts...) where GRPC_XDS_BOOTSTRAP (or the bootstrap file at the default path) lacks the server_listener_resource_name_template field, or it is present but empty. Also triggered when the env var points at a bootstrap JSON intended only for clients.
Common situations: Reusing a client-only bootstrap file for an xDS server; bootstrap generated by a control plane that omits the server template; typo in the field name; bootstrap env var unset so a client-style default is synthesized.
Related errors
- failed to build credentials bundle from bootstrap for
- xds: `channel_creds` field in server config cannot be empty
- xds: config parsing for certificate provider plugin
- xds: error normalizing JSON bootstrap configuration
- xds: failed to JSON unmarshal server configurations during…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/155074cb7ce1f43c.
Report an issue: GitHub.
Appendix: source
Thrown at xds/server.go:111
// Initializing the xDS client upfront (instead of at serving time)
// simplifies the code by eliminating the need for a mutex to protect the
// xdsC and xdsClientClose fields.
pool := xdsClientPool
if s.opts.clientPoolForTesting != nil {
pool = s.opts.clientPoolForTesting
}
xdsClient, xdsClientClose, err := pool.NewClient(xdsclient.NameForServer, mrl)
if err != nil {
return nil, fmt.Errorf("xDS client creation failed: %v", err)
}
// Validate the bootstrap configuration for server specific fields.
// Listener resource name template is mandatory on the server side.
cfg := xdsClient.BootstrapConfig()
if cfg.ServerListenerResourceNameTemplate() == "" {
xdsClientClose()
return nil, errors.New("missing server_listener_resource_name_template in the bootstrap configuration")
}
s.xdsC = xdsClient
s.xdsClientClose = xdsClientClose
s.logger = internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf(serverPrefix, s))
s.logger.Infof("Created xds.GRPCServer")
return s, nil
}
// handleServerOptions iterates through the list of server options passed in by
// the user, and handles the xDS server specific options.
func (s *GRPCServer) handleServerOptions(opts []grpc.ServerOption) {
so := s.defaultServerOptions()
for _, opt := range opts {
if o, ok := opt.(*serverOption); ok {
o.apply(so)View on GitHub (pinned to 0c51461d27)