grpc/grpc-go · error
xds: failed to get security plugin instance (%+v)
Error message
xds: failed to get security plugin instance (%+v): %v
What it means
Returned by buildProviderFunc (clusterimpl.go:323) when cfg.Build() fails for a certificate provider plugin during xDS security config processing. The %+v shows the full provider BuildableConfig struct (for diagnostics) and %v shows the Build error. The comment (lines 319-322) notes this is unexpected because bootstrap already parsed and validated the config, but Build() can still fail at instantiation time (e.g., file not found, plugin unavailable).
Solutions
- Inspect the %+v to see which certificate provider instance name and config is failing.
- Verify the certificate and key files referenced in the bootstrap config exist and are readable by the process: 'ls -la /path/to/cert' and check file permissions.
- Validate the bootstrap JSON: ensure the certificate_provider_instances section has correct plugin configs with valid file paths.
- If using a custom cert provider plugin, debug its Build() method for the specific error.
- Confirm the cert and key files are valid PEM/DER and the key matches the certificate.
- Check if the bootstrap config's credential_instance_name matches what the xDS server's security config references.
Example fix
// before: bootstrap references missing cert files
{
"certificate_provider_instances": {
"default": {
"plugin_name": "file_watcher",
"config": {
"certificate_file": "/etc/certs/server.crt",
"private_key_file": "/etc/certs/server.key"
}
}
}
}
// certs don't exist at those paths
// after: ensure files exist and are readable, or fix paths
// ls -la /etc/certs/server.crt /etc/certs/server.key
// chmod 644 /etc/certs/server.crt && chmod 600 /etc/certs/server.key
// or update bootstrap JSON with correct paths before starting the client Defensive patterns
Strategy: validation
Validate before calling
// Validate certificate provider config before the channel uses it.
// Check that referenced files exist and are readable:
func validateCertProviderFiles(bootstrapPath string) error {
data, err := os.ReadFile(bootstrapPath)
if err != nil {
return fmt.Errorf("cannot read bootstrap: %w", err)
}
// Parse and check file_watcher plugin paths
var bs struct {
CertProviderInstances map[string]struct {
PluginName string `json:"plugin_name"`
Config struct {
CertFile string `json:"certificate_file"`
KeyFile string `json:"private_key_file"`
RootCertFile string `json:"root_certificate_file"`
} `json:"config"`
} `json:"certificate_provider_instances"`
}
json.Unmarshal(data, &bs)
for name, inst := range bs.CertProviderInstances {
if inst.PluginName == "file_watcher" {
for _, f := range []string{inst.Config.CertFile, inst.Config.KeyFile, inst.Config.RootCertFile} {
if f != "" {
if _, err := os.Stat(f); err != nil {
return fmt.Errorf("instance %q: file %q: %w", name, f, err)
}
}
}
}
}
return nil
} Try / catch
// This error propagates from cluster_impl's handleSecurityConfig
// through UpdateClientConnState. The channel enters TRANSIENT_FAILURE.
err := getChannelError(conn)
if err != nil && strings.Contains(err.Error(), "failed to get security plugin") {
// inspect the %+v in the message for the provider instance name
// check certificate files and bootstrap config
log.Printf("cert provider build failed: %v", err)
} Prevention
- Validate the bootstrap configuration's certificate provider section before starting the client.
- Ensure certificate and key files exist, are valid PEM, and are readable by the process.
- Use a file watcher or cert manager to ensure certs are present and rotated.
- Test the bootstrap config in staging with the same cert layout as production.
- Verify the identity/root instance names in the security config match the bootstrap's certificate_provider_instances keys.
When it happens
Trigger: handleSecurityConfig (line 359) is called during a cluster_impl UpdateClientConnState when the cluster resource contains a SecurityConfig. It calls buildProviders (line 328) which calls buildProviderFunc for root and/or identity certificate providers. cfg.Build() fails because the certificate provider plugin (e.g., file-based cert provider) cannot initialize — missing cert files, wrong paths, permission denied, or a custom plugin that errors on startup.
Common situations: The bootstrap configuration references certificate files that don't exist at the specified path. The certificate provider plugin (e.g., Google S2A, FileWatcher) fails to initialize because its specific config is wrong (wrong cert file format, key mismatch). Permissions issue reading the cert/key files. The bootstrap JSON was generated for a different environment (e.g., dev bootstrap used in prod). A custom cert provider plugin that returns an error from Build().
Related errors
- failed to build credentials bundle from bootstrap for
- overriding server name is not supported by xDS client TLS…
- received Cluster resource that contains invalid security…
- xds: config parsing for certificate provider plugin
- xds: fetching identity certificates from…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/e25aa8ec8ef048d1.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/balancer/clusterimpl/clusterimpl.go:323
b.loadWrapper.UpdateLoadStore(loadStore)
}
return nil
}
func buildProviderFunc(configs map[string]*certprovider.BuildableConfig, instanceName, certName string, wantIdentity, wantRoot bool) (certprovider.Provider, error) {
cfg := configs[instanceName]
provider, err := cfg.Build(certprovider.BuildOptions{
CertName: certName,
WantIdentity: wantIdentity,
WantRoot: wantRoot,
})
if err != nil {
// This error is not expected since the bootstrap process parses the
// config and makes sure that it is acceptable to the plugin. Still, it
// is possible that the plugin parses the config successfully, but its
// Build() method errors out.
return nil, fmt.Errorf("xds: failed to get security plugin instance (%+v): %v", cfg, err)
}
return provider, nil
}
func (b *clusterImplBalancer) buildProviders(config *xdsresource.SecurityConfig) (certprovider.Provider, certprovider.Provider, error) {
cpc := b.xdsClient.BootstrapConfig().CertProviderConfigs()
var rootProvider certprovider.Provider
if config.UseSystemRootCerts {
rootProvider = systemRootCertsProvider{}
} else {
rp, err := buildProvider(cpc, config.RootInstanceName, config.RootCertName, false, true)
if err != nil {
return nil, nil, err
}
rootProvider = rp
}
var identityProvider certprovider.ProviderView on GitHub (pinned to 0c51461d27)