{"record":{"id":"69ff11dd68512ea6","repo":"grpc/grpc-go","slug":"fault-error-parsing-config-v-unknown-type-t","errorCode":null,"errorMessage":"fault: error parsing config %v: unknown type %T","messagePattern":"fault: error parsing config (.+?): unknown type %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/fault/fault.go","lineNumber":87,"sourceCode":"}\n\ntype config struct {\n\thttpfilter.FilterConfig\n\tconfig *fpb.HTTPFault\n}\n\nfunc (builder) TypeURLs() []string {\n\treturn []string{\"type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault\"}\n}\n\n// Parsing is the same for the base config and the override config.\nfunc parseConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {\n\tif cfg == nil {\n\t\treturn nil, fmt.Errorf(\"fault: nil configuration message provided\")\n\t}\n\tm, ok := cfg.(*anypb.Any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"fault: error parsing config %v: unknown type %T\", cfg, cfg)\n\t}\n\tmsg := new(fpb.HTTPFault)\n\tif err := m.UnmarshalTo(msg); err != nil {\n\t\treturn nil, fmt.Errorf(\"fault: error parsing config %v: %v\", cfg, err)\n\t}\n\treturn config{config: msg}, nil\n}\n\nfunc (builder) ParseFilterConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {\n\treturn parseConfig(cfg)\n}\n\nfunc (builder) ParseFilterConfigOverride(override proto.Message) (httpfilter.FilterConfig, error) {\n\treturn parseConfig(override)\n}\n\nfunc (builder) IsTerminal() bool {\n\treturn false","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/httpfilter/fault/fault.go#L69-L105","documentation":"parseConfig (fault.go:85) requires the cfg to be *anypb.Any. The type assertion fails for any other concrete proto.Message type (e.g., passing the *fpb.HTTPFault directly instead of wrapping it).","triggerScenarios":"ParseFilterConfig is called with a proto.Message that is not *anypb.Any — most commonly a *fpb.HTTPFault, *fpb.HTTPFault pointer, or a different filter's config proto.","commonSituations":"Programmatic test/registration that passes the unwrapped filter proto; cross-wiring configs between filters; control-plane bug that sends the raw proto instead of an Any.","solutions":["Wrap the HTTPFault proto in an anypb.Any using anypb.New before passing it in.","Verify the type URL matches type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault.","Use the builder's TypeURLs() list as the source of truth for acceptable URLs."],"exampleFix":"// before\ncfg, err := faultBuilder.ParseFilterConfig(&fpb.HTTPFault{...})\n\n// after\nanyCfg, err := anypb.New(&fpb.HTTPFault{...})\ncfg, err := faultBuilder.ParseFilterConfig(anyCfg)","handlingStrategy":"type-guard","validationCode":"if _, ok := cfg.(*anypb.Any); !ok {\n    return nil, fmt.Errorf(\"fault: expected *anypb.Any, got %T\", cfg)\n}","typeGuard":"func isAnyPB(m proto.Message) bool { _, ok := m.(*anypb.Any); return ok }","tryCatchPattern":"if _, ok := cfg.(*anypb.Any); !ok {\n    anyCfg, err := anypb.New(cfg)\n    if err != nil { return err }\n    cfg = anyCfg\n}\nfc, err := faultBuilder.ParseFilterConfig(cfg)","preventionTips":["Always wrap filter config protos in anypb.New before handing them to ParseFilterConfig.","Add a builder-level test that feeds *anypb.Any only."],"tags":["fault","config","type","xds","grpc"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}