grpc/grpc-go · critical

xds: failed to JSON unmarshal server configurations during b

Error message

xds: failed to JSON unmarshal server configurations during bootstrap: %v, config:
%s

What it means

Returned by ServerConfigs.UnmarshalJSON (internal/xds/bootstrap/bootstrap.go:143) when the top-level `xds_servers` array fails to unmarshal into []*ServerConfig. This happens during bootstrap parsing (GetConfiguration/NewConfigFromContents) and is fatal: the xDS client cannot start without valid server configs.

Source

Thrown at internal/xds/bootstrap/bootstrap.go:144

// Equal returns true if scs equals other.
func (scs *ServerConfigs) Equal(other *ServerConfigs) bool {
	if len(*scs) != len(*other) {
		return false
	}
	for i := range *scs {
		if !(*scs)[i].Equal((*other)[i]) {
			return false
		}
	}
	return true
}

// UnmarshalJSON takes the json data (a list of server configurations) and
// unmarshals it to the struct.
func (scs *ServerConfigs) UnmarshalJSON(data []byte) error {
	servers := []*ServerConfig{}
	if err := json.Unmarshal(data, &servers); err != nil {
		return fmt.Errorf("xds: failed to JSON unmarshal server configurations during bootstrap: %v, config:\n%s", err, string(data))
	}
	*scs = servers
	return nil
}

// String returns a string representation of the ServerConfigs, by concatenating
// the string representations of the underlying server configs.
func (scs *ServerConfigs) String() string {
	ret := ""
	for i, sc := range *scs {
		if i > 0 {
			ret += ", "
		}
		ret += sc.String()
	}
	return ret
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Validate the bootstrap file with a JSON linter and against the xDS bootstrap schema
  2. Ensure `xds_servers` is an array of objects each with `server_uri` and `channel_creds`
  3. Point GRPC_XDS_BOOTSTRAP at a known-good file (re-check the path)

Example fix

// before
{"xds_servers":{"server_uri":"trafficdirector.googleapis.com"}}
// after
{"xds_servers":[{"server_uri":"trafficdirector.googleapis.com","channel_creds":[{"type":"google_default"}]}]}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the bootstrap file before feeding it to the xDS client.
data, err := os.ReadFile(bootstrapPath)
if err != nil { return err }
if !json.Valid(data) {
    return fmt.Errorf("bootstrap file %q is not valid JSON", bootstrapPath)
}
var probe struct{ XDSServers []json.RawMessage `json:"xds_servers"` }
if err := json.Unmarshal(data, &probe); err != nil || len(probe.XDSServers) == 0 {
    return fmt.Errorf("bootstrap `xds_servers` missing or invalid: %v", err)
}

Try / catch

cfg, err := bootstrap.GetConfiguration()
if err != nil {
    log.Fatalf("xDS bootstrap failed; check GRPC_XDS_BOOTSTRAP: %v", err)
}

Prevention

When it happens

Trigger: Bootstrap JSON's `xds_servers` field is not a valid JSON array of server objects — e.g. it is a string, an object instead of an array, or contains malformed entries that fail ServerConfig unmarshalling.

Common situations: Hand-edited bootstrap file with a structural mistake; GRPC_XDS_BOOTSTRAP points at a truncated/corrupt file; GRPC_XDS_BOOTSTRAP_CONFIG env var holds invalid JSON; a server entry missing required fields.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/05df2203bd9f6fdc. Report an issue: GitHub.