{"record":{"id":"5e24bb381877d1e8","repo":"grpc/grpc-go","slug":"fault-incorrect-override-config-type-provided-t","errorCode":null,"errorMessage":"fault: incorrect override config type provided (%T): %v","messagePattern":"fault: incorrect override config type provided \\(%T\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/fault/fault.go","lineNumber":133,"sourceCode":"\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}\n\ntype interceptor struct {\n\tconfig *fpb.HTTPFault\n}\n\nvar activeFaults uint32 // global active faults; accessed atomically\n\nfunc (i *interceptor) NewStream(ctx context.Context, _ iresolver.RPCInfo, newStream func(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStream, error), opts ...grpc.CallOption) (grpc.ClientStream, error) {","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/httpfilter/fault/fault.go#L115-L151","documentation":"When an override config is present, BuildClientInterceptor requires it to be the fault builder's own config type (fault.go:131). A non-fault override type is rejected because the override fully replaces the base config and must be structurally compatible.","triggerScenarios":"override passed to BuildClientInterceptor is non-nil but not the internal fault config struct (e.g. it came from a different filter builder or was never parsed by the fault builder).","commonSituations":"Per-route override decoded by the wrong builder; override config object reused across filters; framework that supplies a generic override wrapper.","solutions":["Route per-route fault overrides through ParseFilterConfigOverride of the fault builder so they are the correct type.","Pass nil for override when no per-route fault config applies.","Verify the per-route typed config's TypeURL resolves to the fault builder, not a sibling filter."],"exampleFix":"// before: override is the raw HTTPFault or a foreign config\nic, err := cf.BuildClientInterceptor(base, foreignOverride)\n\n// after: override produced by the fault builder's override parser\noverride, err := faultBuilder.ParseFilterConfigOverride(overrideAny)\nic, err := cf.BuildClientInterceptor(base, override)","handlingStrategy":"type-guard","validationCode":"if override != nil {\n    // override must be produced by the fault builder's ParseFilterConfigOverride\n}","typeGuard":"// Override type is unexported; ensure it came from ParseFilterConfigOverride of the same builder.","tryCatchPattern":"ic, err := cf.BuildClientInterceptor(cfg, override)\nif err != nil {\n    return err\n}","preventionTips":["Route per-route overrides through the matching builder's override parser.","Pass nil when no override applies.","Verify the per-route TypeURL resolves to the fault builder."],"tags":["fault-injection","grpc","xds","config","type-mismatch","go"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}