grpc/grpc-go · error
xds: required field `xds_servers` not found in bootstrap…
Error message
xds: required field `xds_servers` not found in bootstrap configuration: %s
What it means
Returned by Config.UnmarshalJSON when the xds_servers field is absent or an empty array. xds_servers is the only strictly required top-level field; without at least one management server the xDS client cannot operate.
Solutions
- Add an xds_servers array with at least one valid server object.
- Verify the GRPC_XDS_BOOTSTRAP / GRPC_XDS_BOOTSTRAP_FILE_NAME env var points to the intended file.
- Check the field name spelling (snake_case xds_servers).
- Regenerate the bootstrap from your control plane.
Example fix
// before
{"node":{"id":"test"}}
// after
{"xds_servers":[{"server_uri":"trafficdirector.googleapis.com:443","channel_creds":[{"type":"google_default"}]}],"node":{"id":"test"}} Defensive patterns
Strategy: validation
Validate before calling
// Ensure xds_servers is present and non-empty before deploy.
func hasXDSServers(data []byte) error {
var top struct {
XDSServers []json.RawMessage `json:"xds_servers"`
}
if err := json.Unmarshal(data, &top); err != nil {
return err
}
if len(top.XDSServers) == 0 {
return fmt.Errorf("xds_servers missing or empty")
}
return nil
} Try / catch
if _, err := bootstrap.GetConfiguration(); err != nil {
if strings.Contains(err.Error(), "xds_servers") {
// add at least one server to the bootstrap.
}
} Prevention
- Treat xds_servers as mandatory in your bootstrap template.
- Point GRPC_XDS_BOOTSTRAP at a file you have validated.
- Add a CI check that fails when xds_servers is absent.
When it happens
Trigger: Triggered at bootstrap.go:631 when len(c.xDSServers) == 0 after unmarshalling succeeds structurally.
Common situations: Bootstrap file omits xds_servers; field misspelled (e.g. 'xdsServers'); GRPC_XDS_BOOTSTRAP env var points to a stale or wrong file that lacks the field.
Related errors
- failed to build credentials bundle from bootstrap for
- missing server_listener_resource_name_template in the…
- xds: `channel_creds` field in server config cannot be empty
- xds: config parsing for certificate provider plugin
- xds: error normalizing JSON bootstrap configuration
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/f9f46496bac64d37.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/bootstrap/bootstrap.go:631
parser := getBuilder(nameAndConfig.PluginName)
if parser == nil {
// We ignore plugins that we do not know about.
continue
}
bc, err := parser.ParseConfig(nameAndConfig.Config)
if err != nil {
return fmt.Errorf("xds: config parsing for certificate provider plugin %q failed during bootstrap: %v", name, err)
}
cpcCfgs[instance] = bc
}
c.certProviderConfigs = cpcCfgs
// Default value of the default client listener name template is "%s".
if c.clientDefaultListenerResourceNameTemplate == "" {
c.clientDefaultListenerResourceNameTemplate = "%s"
}
if len(c.xDSServers) == 0 {
return fmt.Errorf("xds: required field `xds_servers` not found in bootstrap configuration: %s", string(data))
}
// Post-process the authorities' client listener resource template field:
// - if set, it must start with "xdstp://<authority_name>/"
// - if not set, it defaults to "xdstp://<authority_name>/envoy.config.listener.v3.Listener/%s"
for name, authority := range c.authorities {
prefix := fmt.Sprintf("xdstp://%s", url.PathEscape(name))
if authority.ClientListenerResourceNameTemplate == "" {
authority.ClientListenerResourceNameTemplate = prefix + "/envoy.config.listener.v3.Listener/%s"
continue
}
if !strings.HasPrefix(authority.ClientListenerResourceNameTemplate, prefix) {
return fmt.Errorf("xds: field clientListenerResourceNameTemplate %q of authority %q doesn't start with prefix %q", authority.ClientListenerResourceNameTemplate, name, prefix)
}
}
return nil
}
View on GitHub (pinned to 0c51461d27)