{"record":{"id":"27caf130b78d6384","repo":"grpc/grpc-go","slug":"meshca-unsupported-config-type-t","errorCode":null,"errorMessage":"meshca: unsupported config type: %T","messagePattern":"meshca: unsupported config type: %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/tls/certprovider/pemfile/builder.go","lineNumber":47,"sourceCode":"\t\"google.golang.org/protobuf/types/known/durationpb\"\n)\n\nconst (\n\t// PluginName is the name of the PEM file watcher plugin.\n\tPluginName             = \"file_watcher\"\n\tdefaultRefreshInterval = 10 * time.Minute\n)\n\nfunc init() {\n\tcertprovider.Register(&pluginBuilder{})\n}\n\ntype pluginBuilder struct{}\n\nfunc (p *pluginBuilder) ParseConfig(c any) (*certprovider.BuildableConfig, error) {\n\tdata, ok := c.(json.RawMessage)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"meshca: unsupported config type: %T\", c)\n\t}\n\topts, err := pluginConfigFromJSON(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn certprovider.NewBuildableConfig(PluginName, opts.canonical(), func(certprovider.BuildOptions) certprovider.Provider {\n\t\treturn newProvider(opts)\n\t}), nil\n}\n\nfunc (p *pluginBuilder) Name() string {\n\treturn PluginName\n}\n\nfunc pluginConfigFromJSON(jd json.RawMessage) (Options, error) {\n\t// The only difference between this anonymous struct and the Options struct\n\t// is that the refresh_interval is represented here as a duration proto,\n\t// while in the latter a time.Duration is used.","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/credentials/tls/certprovider/pemfile/builder.go#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncfg := map[string]string{\"certificate_file\": \"/etc/certs/cert.pem\"}\nbc, err := builder.ParseConfig(cfg) // wrong type -> meshca: unsupported config type: map[string]string\n\n// after\nraw, _ := json.Marshal(cfg)\nbc, err := builder.ParseConfig(json.RawMessage(raw)) // json.RawMessage accepted","handlingStrategy":"validation","validationCode":"raw, err := json.Marshal(cfgMap)\nif err != nil { return err }\nbc, err := builder.ParseConfig(json.RawMessage(raw)) // pass json.RawMessage, not the map\nif err != nil { return err }","typeGuard":"func isRawMessage(c any) bool {\n    _, ok := c.(json.RawMessage)\n    return ok\n}","tryCatchPattern":"bc, err := builder.ParseConfig(cfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"unsupported config type\") {\n        // registry gave a non-JSON type; json.Marshal your config first,\n        // or update xDS bootstrap + grpc-go to matching versions\n    }\n    return err\n}","preventionTips":["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."],"tags":["xds","configuration","certprovider","validation","go","internal"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}