grpc/grpc-go · error
meshca: unsupported config type: %T
Error message
meshca: unsupported config type: %T
What it means
Returned by the pem-file certprovider pluginBuilder.ParseConfig (builder.go:47) when the config value passed in is not a json.RawMessage. Note the message prefix says "meshca" — this is a copy-paste artifact in the pemfile package source; the error actually originates in the file_watcher (PEM file) provider, not MeshCA. The certprovider registry dispatches parsed config as json.RawMessage, so a non-JSON type indicates an internal/registry misuse rather than user input.
Source
Thrown at credentials/tls/certprovider/pemfile/builder.go:47
"google.golang.org/protobuf/types/known/durationpb"
)
const (
// PluginName is the name of the PEM file watcher plugin.
PluginName = "file_watcher"
defaultRefreshInterval = 10 * time.Minute
)
func init() {
certprovider.Register(&pluginBuilder{})
}
type pluginBuilder struct{}
func (p *pluginBuilder) ParseConfig(c any) (*certprovider.BuildableConfig, error) {
data, ok := c.(json.RawMessage)
if !ok {
return nil, fmt.Errorf("meshca: unsupported config type: %T", c)
}
opts, err := pluginConfigFromJSON(data)
if err != nil {
return nil, err
}
return certprovider.NewBuildableConfig(PluginName, opts.canonical(), func(certprovider.BuildOptions) certprovider.Provider {
return newProvider(opts)
}), nil
}
func (p *pluginBuilder) Name() string {
return PluginName
}
func pluginConfigFromJSON(jd json.RawMessage) (Options, error) {
// The only difference between this anonymous struct and the Options struct
// is that the refresh_interval is represented here as a duration proto,
// while in the latter a time.Duration is used.View on GitHub (pinned to 03255a9237)
Solutions
- Always feed config to the certprovider registry as json.RawMessage (json.Marshal your struct first).
- Use certprovider.GetProvider / the generated BuildableConfig path rather than calling ParseConfig directly with non-JSON types.
- If you hit this from xDS, update the xDS bootstrap and grpc-go to matching versions so the registry hands the expected type.
- Report the misleading 'meshca' prefix as a doc/message bug upstream if it is causing confusion.
Example fix
// before
cfg := map[string]string{"certificate_file": "/etc/certs/cert.pem"}
bc, err := builder.ParseConfig(cfg) // wrong type -> meshca: unsupported config type: map[string]string
// after
raw, _ := json.Marshal(cfg)
bc, err := builder.ParseConfig(json.RawMessage(raw)) // json.RawMessage accepted Defensive patterns
Strategy: validation
Validate before calling
raw, err := json.Marshal(cfgMap)
if err != nil { return err }
bc, err := builder.ParseConfig(json.RawMessage(raw)) // pass json.RawMessage, not the map
if err != nil { return err } Type guard
func isRawMessage(c any) bool {
_, ok := c.(json.RawMessage)
return ok
} Try / catch
bc, err := builder.ParseConfig(cfg)
if err != nil {
if strings.Contains(err.Error(), "unsupported config type") {
// registry gave a non-JSON type; json.Marshal your config first,
// or update xDS bootstrap + grpc-go to matching versions
}
return err
} Prevention
- Always pass certprovider config through the registry as json.RawMessage.
- Use the public certprovider.GetProvider path rather than calling ParseConfig directly.
- Keep xDS bootstrap and grpc-go versions aligned so the registry hands the expected type.
When it happens
Trigger: Programmatic registration or ParseConfig invocation passing a non-json.RawMessage value (a string, map, or struct) to the file_watcher pluginBuilder; an xDS-bootstrap code path or custom provider glue that bypassed JSON marshalling before calling ParseConfig.
Common situations: Custom code that constructs certprovider plugins directly instead of going through certprovider.BuildableConfig / NewBuildableConfig; an internal/xDS version skew where the registry hands the wrong type; tests that call ParseConfig with a raw map.
Related errors
- tokenFilePath cannot be empty
- scheme is not supported: %q. Only http(s) is supported
- xds_wrr_locality: config generated %v is invalid: %v
- gcpauthn: cache_config.cache_size must be greater than zero
- rbac: principal header matcher for %v is :scheme or starts w
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/27caf130b78d6384.
Report an issue: GitHub.