grpc/grpc-go · error

xds: error normalizing JSON bootstrap configuration: %v

Error message

xds: error normalizing JSON bootstrap configuration: %v

What it means

NewConfigFromContents first runs json.Indent on the raw bytes to normalize whitespace (bootstrap.go:692-694). json.Indent requires well-formed JSON input; if the bytes are not valid JSON it returns an error that is wrapped here. This is an earlier, stricter check than UnmarshalJSON and catches malformed input before the structured parse even begins.

Source

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

	if fContent != "" {
		if logger.V(2) {
			logger.Infof("Using bootstrap contents from GRPC_XDS_BOOTSTRAP_CONFIG environment variable")
		}
		return NewConfigFromContents([]byte(fContent))
	}

	return nil, nil
}

// NewConfigFromContents creates a new bootstrap configuration from the provided
// contents.
func NewConfigFromContents(data []byte) (*Config, error) {
	// Normalize the input configuration.
	buf := bytes.Buffer{}
	err := json.Indent(&buf, data, "", "")
	if err != nil {
		return nil, fmt.Errorf("xds: error normalizing JSON bootstrap configuration: %v", err)
	}
	data = bytes.TrimSpace(buf.Bytes())

	config := &Config{}
	if err := config.UnmarshalJSON(data); err != nil {
		return nil, err
	}
	return config, nil
}

// ConfigOptionsForTesting specifies options for creating a new bootstrap
// configuration for testing purposes.
//
// # Testing-Only
type ConfigOptionsForTesting struct {
	// Servers is the top-level xDS server configuration. It contains a list of
	// server configurations.
	Servers json.RawMessage

View on GitHub (pinned to 03255a9237)

Solutions

  1. Confirm the input is JSON by piping it through jq or a JSON parser.
  2. If you have YAML, convert it to JSON before setting GRPC_XDS_BOOTSTRAP_CONFIG or writing the file.
  3. Ensure the full content is present — check for truncation in env var injection or ConfigMap size limits.
  4. For empty input, note that GetConfiguration returns (nil, nil) when neither env var is set, so this error specifically means a non-empty but invalid value.

Example fix

// before: GRPC_XDS_BOOTSTRAP_CONFIG contains YAML
//   xds_servers:
//     - server_uri: dns:///xds:443
// after: provide valid JSON
//   {"xds_servers":[{"server_uri":"dns:///xds:443"}]}
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the contents are JSON before NewConfigFromContents.
func isValidJSON(data []byte) error {
    var buf bytes.Buffer
    if err := json.Indent(&buf, data, "", ""); err != nil {
        return fmt.Errorf("not valid JSON: %w", err)
    }
    return nil
}

Prevention

When it happens

Trigger: Calling NewConfigFromContents (or GetConfiguration via GRPC_XDS_BOOTSTRAP_CONFIG) with bytes that are not valid JSON — empty bytes, a YAML/markup document, a protobuf binary, or truncated JSON. json.Indent fails before any field-level parsing.

Common situations: Passing a YAML bootstrap where JSON was expected; an env var contains a base64 or otherwise encoded blob that was not decoded first; the content was truncated by a shell or config-map size limit.

Related errors


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