grpc/grpc-go · error

failed to build credentials bundle from bootstrap for

Error message

failed to build credentials bundle from bootstrap for %q: %v

What it means

Returned when the first supported channel credentials type's Build() call fails during bootstrap server config parsing. The credential type name (e.g. 'tlscreds_mtls' or 'google_default') is printed along with the underlying build error.

Solutions

  1. Read the underlying %v: it states which file or config value is invalid.
  2. Verify every file path (certificate_file, private_key_file, ca_certificate_file) exists and is readable by the process.
  3. Check file permissions and, in containers, that the secret/mount is present.
  4. Validate the credential plugin config block against the plugin's documented schema.

Example fix

// before (cert file missing)
"channel_creds":[{"type":"tlscreds_mtls","config":{"certificate_file":"/etc/certs/client.crt","private_key_file":"/etc/certs/client.key"}}]
// where /etc/certs/client.key is absent -> error 386

// after: ensure the files exist and are mounted
$ ls /etc/certs/client.crt /etc/certs/client.key
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight check that credential files referenced by channel_creds exist.
func checkCredFiles(cfg map[string]string) error {
    for field, path := range cfg {
        if path == "" {
            continue
        }
        if _, err := os.Stat(path); err != nil {
            return fmt.Errorf("%s: %w", field, err)
        }
    }
    return nil
}

Try / catch

if _, err := bootstrap.NewConfigFromContents(data); err != nil {
    if strings.Contains(err.Error(), "failed to build credentials bundle") {
        // inspect underlying cause, fix cert paths/permissions, then retry bootstrap.
    }
}

Prevention

When it happens

Trigger: Triggered at bootstrap.go:368 when c.Build(cc.Config) errors for a registered channel credential plugin. Example: the tlscreds NewBundle fails because certificate_file or ca_certificate_file paths are unreadable.

Common situations: TLS/mTLS channel creds reference certificate, key, or CA files that do not exist or have wrong permissions; cert provider plugin returns invalid args; SPIFFE trust bundle map file path invalid.

Related errors


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

Appendix: source

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

	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 = cc
		sc.credsDialOption = grpc.WithCredentialsBundle(bundle)
		if d, ok := bundle.(extraDialOptions); ok {
			sc.extraDialOptions = d.DialOptions()
		}
		sc.cleanups = append(sc.cleanups, cancel)
		break
	}

	if envconfig.XDSBootstrapCallCredsEnabled {
		// Process call credentials - unlike channel creds, we use ALL supported
		// types. Also, call credentials are optional as per gRFC A97.
		for _, cfg := range server.CallCredsConfigs {
			c := bootstrap.GetCallCredentials(cfg.Type)
			if c == nil {
				// Skip unsupported call credential types (don't fail bootstrap).
				continue

View on GitHub (pinned to 0c51461d27)