grpc/grpc-go · error
xds: `server_uri` field in server config cannot be empty
Error message
xds: `server_uri` field in server config cannot be empty: %s
What it means
Returned by ServerConfig.UnmarshalJSON when, after parsing, server_uri is empty. server_uri is mandatory for every xDS server entry because it is the address the xDS client dials.
Solutions
- Add a non-empty server_uri to the offending server object (e.g. 'trafficdirector.googleapis.com:443').
- Check the field spelling: it must be snake_case server_uri.
- If the bootstrap is generated, fix the generator/template.
Example fix
// before
{"channel_creds":[{"type":"google_default"}]}
// after
{"server_uri":"trafficdirector.googleapis.com:443","channel_creds":[{"type":"google_default"}]} Defensive patterns
Strategy: validation
Validate before calling
// Reject server objects missing server_uri before writing the bootstrap file.
func requireServerURI(servers []map[string]any) error {
for i, s := range servers {
uri, _ := s["server_uri"].(string)
if uri == "" {
return fmt.Errorf("servers[%d]: server_uri is required", i)
}
}
return nil
} Try / catch
if _, err := bootstrap.NewConfigFromContents(data); err != nil {
if strings.Contains(err.Error(), "server_uri") {
// add/fix the server_uri field.
}
} Prevention
- Always include server_uri in every server object.
- Use snake_case field names.
- Template the bootstrap from a single source of truth.
When it happens
Trigger: Triggered at bootstrap.go:400 when a server object in xds_servers has no server_uri field or an empty string value.
Common situations: server_uri omitted entirely; field misspelled (e.g. 'serverUri' or 'uri'); value left as empty string when templating the bootstrap.
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/c5291cdad65e4fdf.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/bootstrap/bootstrap.go:400
for _, cfg := range server.CallCredsConfigs {
c := bootstrap.GetCallCredentials(cfg.Type)
if c == nil {
// Skip unsupported call credential types (don't fail bootstrap).
continue
}
callCreds, cancel, err := c.Build(cfg.Config)
if err != nil {
// Call credential validation failed - this should fail bootstrap.
return fmt.Errorf("failed to build call credentials from bootstrap for %q: %v", cfg.Type, err)
}
sc.selectedCallCreds = append(sc.selectedCallCreds, callCreds)
sc.extraDialOptions = append(sc.extraDialOptions, grpc.WithPerRPCCredentials(callCreds))
sc.cleanups = append(sc.cleanups, cancel)
}
}
if sc.serverURI == "" {
return fmt.Errorf("xds: `server_uri` field in server config cannot be empty: %s", string(data))
}
if sc.credsDialOption == nil {
return fmt.Errorf("xds: `channel_creds` field in server config cannot be empty: %s", string(data))
}
return nil
}
// ServerConfigTestingOptions specifies options for creating a new ServerConfig
// for testing purposes.
//
// # Testing-Only
type ServerConfigTestingOptions struct {
// URI is the name of the server corresponding to this server config.
URI string
// ChannelCreds contains a list of channel credentials to use when talking
// to this server. If unspecified, `insecure` credentials will be used.
ChannelCreds []ChannelCreds
// CallCredsConfigs contains a list of call credentials to use for individual RPCsView on GitHub (pinned to 0c51461d27)