grpc/grpc-go · error

xds: error normalizing JSON bootstrap configuration

Error message

xds: error normalizing JSON bootstrap configuration: %v

What it means

Returned by NewConfigFromContents when json.Indent fails on the bootstrap contents, meaning the content is not syntactically valid JSON at all (this runs before any structural unmarshalling).

Solutions

  1. Validate the file with a strict JSON parser: jq . bootstrap.json or python -m json.tool bootstrap.json.
  2. Remove JSON comments and trailing commas.
  3. If you need a config format with comments, generate the JSON from it at deploy time instead of embedding comments.
  4. Re-export the file as UTF-8 without BOM.

Example fix

// before (trailing comma, comments)
{
  // xDS servers
  "xds_servers": [...],  // <-- trailing comma
}

// after (strict JSON)
{
  "xds_servers": [...]
}
Defensive patterns

Strategy: validation

Validate before calling

// Strict JSON syntax check on the bootstrap content.
func validateJSONSyntax(data []byte) error {
    var v any
    dec := json.NewDecoder(bytes.NewReader(data))
    dec.DisallowUnknownFields() // optional
    if err := dec.Decode(&v); err != nil {
        return fmt.Errorf("bootstrap JSON syntax: %w", err)
    }
    if dec.More() {
        return fmt.Errorf("bootstrap has trailing content")
    }
    return nil
}

Try / catch

if _, err := bootstrap.NewConfigFromContents(data); err != nil {
    if strings.Contains(err.Error(), "normalizing JSON") {
        // run the file through jq to find the syntax error.
    }
}

Prevention

When it happens

Trigger: Triggered at bootstrap.go:694 when json.Indent(&buf, data, "", "") errors on the raw bootstrap content (file via GRPC_XDS_BOOTSTRAP or inline via GRPC_XDS_BOOTSTRAP_CONFIG).

Common situations: Trailing comma; unquoted keys; JSON comments (// or /* */); single quotes; YAML mistakenly used; a UTF-8 BOM or stray control characters; truncated file.

Related errors


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

Appendix: 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 0c51461d27)