grpc/grpc-go · error
no certificate provider builder found for %q
Error message
no certificate provider builder found for %q
What it means
certprovider.ParseConfig(name, config) looked up a builder for `name` in the global registry and found none. Builders self-register via certprovider.Register in their init() (e.g. the pemfile plugin registers "file_watcher"), so an unknown name means the plugin package was never imported or the name is misspelled.
Source
Thrown at credentials/tls/certprovider/store.go:183
storeKey: sk,
store: provStore,
}
provStore.providers[sk] = wp
return newSingleCloseWrappedProvider(wp), nil
}
// String returns the provider name and config as a colon separated string.
func (bc *BuildableConfig) String() string {
return fmt.Sprintf("%s:%s", bc.name, string(bc.config))
}
// ParseConfig is a convenience function to create a BuildableConfig given a
// provider name and configuration. Returns an error if there is no registered
// builder for the given name or if the config parsing fails.
func ParseConfig(name string, config any) (*BuildableConfig, error) {
parser := getBuilder(name)
if parser == nil {
return nil, fmt.Errorf("no certificate provider builder found for %q", name)
}
return parser.ParseConfig(config)
}
// GetProvider is a convenience function to create a provider given the name,
// config and build options.
func GetProvider(name string, config any, opts BuildOptions) (Provider, error) {
bc, err := ParseConfig(name, config)
if err != nil {
return nil, err
}
return bc.Build(opts)
}
View on GitHub (pinned to 03255a9237)
Solutions
- Add the blank import for the provider package, e.g. `import _ "google.golang.org/grpc/credentials/tls/certprovider/pemfile"`.
- Verify the exact registered name (pemfile registers PluginName = "file_watcher").
- If you wrote a custom provider, ensure certprovider.Register(&yourBuilder{}) runs in an init() of an imported package.
Example fix
// before
import (
"google.golang.org/grpc/credentials/tls/certprovider"
)
certprovider.ParseConfig("file_watcher", raw)
// after
import (
"google.golang.org/grpc/credentials/tls/certprovider"
_ "google.golang.org/grpc/credentials/tls/certprovider/pemfile"
)
certprovider.ParseConfig("file_watcher", raw) Defensive patterns
Strategy: validation
Validate before calling
func isProviderRegistered(name string) bool {
// no public lookup; rely on a build-time check by attempting a no-op ParseConfig
_, err := certprovider.ParseConfig(name, json.RawMessage(`{}`))
return err == nil || !strings.Contains(err.Error(), "no certificate provider builder")
} Try / catch
bc, err := certprovider.ParseConfig(name, raw)
if err != nil {
if strings.Contains(err.Error(), "no certificate provider builder") {
return fmt.Errorf("forgot to import provider %q? %w", name, err)
}
return err
} Prevention
- Add a blank import of the provider package (e.g. _ .../pemfile) wherever you ParseConfig.
- Centralize provider registration in an init package imported by main.
- Document the registered PluginName for each provider you use.
When it happens
Trigger: Calling ParseConfig("file_watcher", ...) without an `import _ "google.golang.org/grpc/credentials/tls/certprovider/pemfile"` somewhere in the binary; passing a typo like "filesystem_watcher" or "file-watch"; using a provider name from a different gRPC language.
Common situations: Forgetting the blank import of the provider package; renaming a provider name across versions; conditional imports behind build tags that excluded the provider in the active build.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- pemfile: json.Unmarshal(%s) failed: %v
- pemfile: protojson.Unmarshal(%+v) failed: %v
- pemfile: at least one credential file needs to be specified
- pemfile: private key file and identity cert file should be b
- pemfile: certificate and key file must be in the same direct
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/d32e6c6abf1d4748.
Report an issue: GitHub.