{"record":{"id":"77e92c9d8b80c756","repo":"grpc/grpc-go","slug":"q-lb-policy-does-not-implement-a-config-parser","errorCode":null,"errorMessage":"%q LB policy does not implement a config parser","messagePattern":"%q LB policy does not implement a config parser","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/balancer/cdsbalancer/cdsbalancer.go","lineNumber":79,"sourceCode":"// bb implements the balancer.Builder interface to help build a cdsBalancer.\n// It also implements the balancer.ConfigParser interface to help parse the\n// JSON service config, to be passed to the cdsBalancer.\ntype bb struct{}\n\n// Build creates a new CDS balancer with the ClientConn.\nfunc (bb) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {\n\tbuilder := balancer.Get(priority.Name)\n\tif builder == nil {\n\t\t// Shouldn't happen, registered through imported Priority builder. Still,\n\t\t// defensive programming.\n\t\tlogger.Errorf(\"%q LB policy is needed but not registered\", priority.Name)\n\t\treturn nop.NewBalancer(cc, fmt.Errorf(\"%q LB policy is needed but not registered\", priority.Name))\n\t}\n\tparser, ok := builder.(balancer.ConfigParser)\n\tif !ok {\n\t\t// Shouldn't happen, imported Priority builder has this method.\n\t\tlogger.Errorf(\"%q LB policy does not implement a config parser\", priority.Name)\n\t\treturn nop.NewBalancer(cc, fmt.Errorf(\"%q LB policy does not implement a config parser\", priority.Name))\n\t}\n\n\tb := &cdsBalancer{\n\t\tbOpts:             opts,\n\t\tchildConfigParser: parser,\n\t\tclusterConfigs:    make(map[string]*xdsresource.ClusterResult),\n\t\tpriorityConfigs:   make(map[string]*priorityConfig),\n\t\tcc:                cc,\n\t}\n\tb.logger = prefixLogger(b)\n\tb.logger.Infof(\"Created\")\n\treturn b\n}\n\n// Name returns the name of balancers built by this builder.\nfunc (bb) Name() string {\n\treturn cdsName\n}","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/balancer/cdsbalancer/cdsbalancer.go#L61-L97","documentation":"Logged and returned as a nop balancer error in bb.Build() (lines 78-79) when the priority balancer builder does not implement the balancer.ConfigParser interface. The CDS balancer needs to parse child policy JSON through this parser; if the type assertion builder.(balancer.ConfigParser) fails, it cannot function. The code comment at line 77 states this should never happen because the imported Priority builder implements ConfigParser.","triggerScenarios":"balancer.Get(priority.Name) returns a non-nil builder, but that builder does not satisfy balancer.ConfigParser. This would only occur if a different (incorrect) builder was registered under the priority.Name key, or if a fork/modified version of the priority balancer removed the ParseConfig method.","commonSituations":"A forked or vendored version of the priority balancer that does not implement ConfigParser. A name collision where a custom balancer registers under the same name as the priority balancer. Corruption from inconsistent vendoring.","solutions":["Ensure you are using the official grpc-go priority balancer without modifications: check 'go list -m -json google.golang.org/grpc' for the source.","Remove any custom balancer.Register calls that might override the priority.Name registration.","Use the public xds package import rather than internal packages to avoid partial or mismatched registrations."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// Verify the priority builder implements ConfigParser at startup\nfunc validatePriorityBuilderParser() error {\n    b := balancer.Get(\"priority_experimental\")\n    if b == nil {\n        return fmt.Errorf(\"priority builder not found\")\n    }\n    if _, ok := b.(balancer.ConfigParser); !ok {\n        return fmt.Errorf(\"priority builder does not implement ConfigParser\")\n    }\n    return nil\n}","typeGuard":"// Type guard for the ConfigParser interface\nfunc isConfigParser(b balancer.Builder) bool {\n    _, ok := b.(balancer.ConfigParser)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Do not register custom balancers under reserved names like 'priority_experimental'.","Use the official grpc-go priority package unmodified.","Validate balancer interface implementations at startup in debug builds."],"tags":["xds","balancer","config-parser","priority","type-assertion"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}