{"record":{"id":"02a6498a2b5cf709","repo":"grpc/grpc-go","slug":"fault-incorrect-config-type-provided-t-v","errorCode":null,"errorMessage":"fault: incorrect config type provided (%T): %v","messagePattern":"fault: incorrect config type provided \\(%T\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/fault/fault.go","lineNumber":125,"sourceCode":"\nfunc (builder) BuildClientFilter(httpfilter.ClientFilterOptions) httpfilter.ClientFilter {\n\treturn clientFilter{}\n}\n\nvar _ httpfilter.ClientFilterBuilder = builder{}\n\ntype clientFilter struct{}\n\nfunc (clientFilter) Close() {}\n\nfunc (clientFilter) BuildClientInterceptor(cfg, override httpfilter.FilterConfig) (httpfilter.ClientInterceptor, error) {\n\tif cfg == nil {\n\t\treturn nil, fmt.Errorf(\"fault: nil config provided\")\n\t}\n\n\tc, ok := cfg.(config)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"fault: incorrect config type provided (%T): %v\", cfg, cfg)\n\t}\n\n\tif override != nil {\n\t\t// override completely replaces the listener configuration; but we\n\t\t// still validate the listener config type.\n\t\tc, ok = override.(config)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"fault: incorrect override config type provided (%T): %v\", override, override)\n\t\t}\n\t}\n\n\ticfg := c.config\n\tif (icfg.GetMaxActiveFaults() != nil && icfg.GetMaxActiveFaults().GetValue() == 0) ||\n\t\t(icfg.GetDelay() == nil && icfg.GetAbort() == nil) {\n\t\treturn nil, nil\n\t}\n\treturn &interceptor{config: icfg}, nil\n}","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/httpfilter/fault/fault.go#L107-L143","documentation":"BuildClientInterceptor (fault.go:124) requires cfg to be the filter's internal config struct (the unexported type returned by parseConfig). Any other concrete type fails the assertion — usually because a config from a different filter builder was passed in.","triggerScenarios":"BuildClientInterceptor is called with a FilterConfig value that is not the fault filter's internal config struct (e.g., an rbac or gcp_authn config, or a custom implementation of the FilterConfig interface).","commonSituations":"Cross-filter wiring mistake; a wrapper that re-implements httpfilter.FilterConfig and passes its own type; refactoring that swapped builders.","solutions":["Use the config value returned by the fault builder's ParseFilterConfig as the cfg argument.","Do not mix configs across filter builders; each builder produces its own internal type.","Add a unit test that asserts the cfg type matches the builder that produced it."],"exampleFix":"// before\nic, err := faultCF.BuildClientInterceptor(rbacConfig, override)\n\n// after\nic, err := faultCF.BuildClientInterceptor(faultConfig, override)","handlingStrategy":"type-guard","validationCode":"// Internal type is unexported, so guard by ensuring the same builder produced cfg.\n// Caller-side: keep a reference to the builder and use it for both parse and build.","typeGuard":null,"tryCatchPattern":"// The error is returned from BuildClientInterceptor; surface it during filter setup.\nic, err := cf.BuildClientInterceptor(cfg, override)\nif err != nil && strings.Contains(err.Error(), \"incorrect config type\") {\n    // re-parse cfg with the correct builder\n}","preventionTips":["Never substitute a config produced by one builder into another builder's filter.","Keep parse and build calls paired through the same builder instance."],"tags":["fault","config","type","grpc","xds"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}