grpc/grpc-go · error
xds: failed to JSON unmarshal server configuration during…
Error message
xds: failed to JSON unmarshal server configuration during bootstrap: %v, config: %s
What it means
Returned by ServerConfig.UnmarshalJSON when an individual server entry inside xds_servers fails to unmarshal into the serverConfigJSON struct (server_uri, channel_creds, call_creds, server_features). The raw server JSON is printed.
Solutions
- Locate the failing server block using the printed JSON.
- Confirm each field type matches the schema: server_uri string, channel_creds array of {type,config?}, call_creds array, server_features array of strings.
- Validate with a JSON schema for the bootstrap (gRFC xDS bootstrap format).
- Remove optional fields rather than leaving them as wrong-typed placeholders.
Example fix
// before (channel_creds wrong type)
{"server_uri":"td:443","channel_creds":"google_default"}
// after
{"server_uri":"td:443","channel_creds":[{"type":"google_default"}]} Defensive patterns
Strategy: validation
Validate before calling
// Validate a single server config object shape.
func validateServerObject(raw json.RawMessage) error {
var s struct {
ServerURI string `json:"server_uri"`
ChannelCreds []json.RawMessage `json:"channel_creds"`
}
if err := json.Unmarshal(raw, &s); err != nil {
return fmt.Errorf("server object invalid: %w", err)
}
return nil
} Try / catch
if _, err := bootstrap.NewConfigFromContents(data); err != nil {
return fmt.Errorf("bootstrap parse failed (check server blocks): %w", err)
} Prevention
- Match field names exactly: server_uri, channel_creds, call_creds, server_features.
- Use arrays where the schema requires arrays.
- Validate with a JSON schema for the bootstrap format.
When it happens
Trigger: Triggered at bootstrap.go:352 when json.Unmarshal(data, &server) fails for one element of the xds_servers array. Typically one field has an unexpected type, e.g. channel_creds is a string instead of an array of objects.
Common situations: channel_creds spelled wrong or set to a bare string; server_uri is a number; call_creds/server_features not arrays; whitespace or unicode issues inside one server block.
Related errors
- xds: error normalizing JSON bootstrap configuration
- xds: failed to JSON unmarshal server configurations during…
- xds: json.Unmarshal( ) failed during bootstrap
- failed to build credentials bundle from bootstrap for
- failed to unmarshal config
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/58a44bc70195a43e.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/bootstrap/bootstrap.go:352
ServerURI: sc.serverURI,
ChannelCreds: sc.channelCreds,
CallCredsConfigs: sc.callCredsConfigs,
ServerFeatures: sc.serverFeatures,
}
return json.Marshal(server)
}
// extraDialOptions captures custom dial options specified via
// credentials.Bundle.
type extraDialOptions interface {
DialOptions() []grpc.DialOption
}
// UnmarshalJSON takes the json data (a server) and unmarshals it to the struct.
func (sc *ServerConfig) UnmarshalJSON(data []byte) error {
server := serverConfigJSON{}
if err := json.Unmarshal(data, &server); err != nil {
return fmt.Errorf("xds: failed to JSON unmarshal server configuration during bootstrap: %v, config:\n%s", err, string(data))
}
sc.serverURI = server.ServerURI
sc.channelCreds = server.ChannelCreds
sc.callCredsConfigs = server.CallCredsConfigs
sc.serverFeatures = server.ServerFeatures
for _, cc := range server.ChannelCreds {
// We stop at the first credential type that we support.
c := bootstrap.GetChannelCredentials(cc.Type)
if c == nil {
continue
}
bundle, cancel, err := c.Build(cc.Config)
if err != nil {
return fmt.Errorf("failed to build credentials bundle from bootstrap for %q: %v", cc.Type, err)
}
sc.selectedChannelCreds = ccView on GitHub (pinned to 0c51461d27)