grpc/grpc-go · error
xds: config parsing for certificate provider plugin %q faile
Error message
xds: config parsing for certificate provider plugin %q failed during bootstrap: %v
What it means
During bootstrap unmarshalling the library iterates every entry in certificate_providers, looks up the registered provider builder for the plugin name, and calls ParseConfig on that builder's config block. This error fires when a known provider plugin rejects its own config sub-document. The plugin name and the underlying parse error are both reported.
Source
Thrown at internal/xds/bootstrap/bootstrap.go:620
c.cpcs = config.CertificateProviders
c.serverListenerResourceNameTemplate = config.ServerListenerResourceNameTemplate
c.clientDefaultListenerResourceNameTemplate = config.ClientDefaultListenerResourceNameTemplate
c.authorities = config.Authorities
c.node = config.Node
// Build the certificate providers configuration to ensure that it is valid.
cpcCfgs := make(map[string]*certprovider.BuildableConfig)
getBuilder := internal.GetCertificateProviderBuilder.(func(string) certprovider.Builder)
for instance, nameAndConfig := range c.cpcs {
name := nameAndConfig.PluginName
parser := getBuilder(nameAndConfig.PluginName)
if parser == nil {
// We ignore plugins that we do not know about.
continue
}
bc, err := parser.ParseConfig(nameAndConfig.Config)
if err != nil {
return fmt.Errorf("xds: config parsing for certificate provider plugin %q failed during bootstrap: %v", name, err)
}
cpcCfgs[instance] = bc
}
c.certProviderConfigs = cpcCfgs
// Default value of the default client listener name template is "%s".
if c.clientDefaultListenerResourceNameTemplate == "" {
c.clientDefaultListenerResourceNameTemplate = "%s"
}
if len(c.xDSServers) == 0 {
return fmt.Errorf("xds: required field `xds_servers` not found in bootstrap configuration: %s", string(data))
}
// Post-process the authorities' client listener resource template field:
// - if set, it must start with "xdstp://<authority_name>/"
// - if not set, it defaults to "xdstp://<authority_name>/envoy.config.listener.v3.Listener/%s"
for name, authority := range c.authorities {
prefix := fmt.Sprintf("xdstp://%s", url.PathEscape(name))View on GitHub (pinned to 03255a9237)
Solutions
- Check the named plugin in the error message and review its required fields against the pemfile (file_watcher) provider schema: at least one of certificate_file or ca_certificate_file must be set.
- Ensure every file path in the config block exists and is readable by the process at bootstrap time.
- Validate the certificate_providers stanza with the provider's documentation before deploying.
- If the plugin is not actually needed, remove the entry rather than leaving a partial config.
Example fix
// before:
// "certificate_providers": {
// "default": { "plugin_name": "file_watcher", "config": {} }
// }
// after:
// "certificate_providers": {
// "default": {
// "plugin_name": "file_watcher",
// "config": { "certificate_file": "/etc/certs/client.pem",
// "private_key_file": "/etc/certs/client.key",
// "ca_certificate_file": "/etc/certs/ca.pem" }
// }
// } Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate the certificate_providers stanza against known schemas.
func validateCertProviders(raw map[string]json.RawMessage) error {
for inst, b := range raw {
var entry struct{ PluginName string `json:"plugin_name"`; Config map[string]any `json:"config"` }
if err := json.Unmarshal(b, &entry); err != nil {
return fmt.Errorf("%s: %w", inst, err)
}
if entry.PluginName == "file_watcher" {
if _, ok := entry.Config["certificate_file"]; !ok {
if _, ok := entry.Config["ca_certificate_file"]; !ok {
return fmt.Errorf("%s: file_watcher needs certificate_file or ca_certificate_file", inst)
}
}
}
}
return nil
} Prevention
- Keep a JSON schema for the certificate_providers section and validate against it in CI.
- Cross-check every plugin config against the pemfile provider documentation before deploy.
- Use a bootstrap generator rather than hand-writing the providers map.
When it happens
Trigger: A certificate_providers entry references a registered plugin (e.g. file_watcher) but its inline config object is missing a required field such as certificate_file/private_key_file/ca_certificate_file, or passes a value with the wrong type. Unknown plugin names are silently skipped, so this error only appears for recognized plugins whose ParseConfig returns an error.
Common situations: Switching from system-roots to mTLS and forgetting to add certificate_file + private_key_file to the file_watcher config; referencing a cert path that the schema expects as a nested object; mismatch between the file_watcher schema version and the bootstrap format.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- missing server_listener_resource_name_template in the bootst
- xds: failed to JSON unmarshal server configurations during b
- xds: failed to JSON unmarshal server configuration during bo
- failed to build credentials bundle from bootstrap for %q: %v
- failed to build call credentials from bootstrap for %q: %v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/dd6061c872a588ee.
Report an issue: GitHub.