{"record":{"id":"aa37933597a2d32e","repo":"grpc/grpc-go","slug":"extproc-error-parsing-config-v-unknown-type-t","errorCode":null,"errorMessage":"extproc: error parsing config %v: unknown type %T, want *anypb.Any","messagePattern":"extproc: error parsing config (.+?): unknown type %T, want \\*anypb\\.Any","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/extproc/ext_proc.go","lineNumber":112,"sourceCode":"// NONE or GRPC. Also ensures that if response body mode is GRPC then response\n// trailer mode must be SEND.\nfunc validateBodyProcessingMode(mode *v3procfilterpb.ProcessingMode) error {\n\tif m := mode.GetRequestBodyMode(); m != v3procfilterpb.ProcessingMode_NONE && m != v3procfilterpb.ProcessingMode_GRPC {\n\t\treturn fmt.Errorf(\"extproc: invalid request body mode %v: want %q or %q\", m, \"NONE\", \"GRPC\")\n\t}\n\tif m := mode.GetResponseBodyMode(); m != v3procfilterpb.ProcessingMode_NONE && m != v3procfilterpb.ProcessingMode_GRPC {\n\t\treturn fmt.Errorf(\"extproc: invalid response body mode %v: want %q or %q\", m, \"NONE\", \"GRPC\")\n\t}\n\tif mode.GetResponseBodyMode() == v3procfilterpb.ProcessingMode_GRPC && mode.GetResponseTrailerMode() != v3procfilterpb.ProcessingMode_SEND {\n\t\treturn fmt.Errorf(\"extproc: invalid response trailer mode %v: must be %q when response body mode is %q\", mode.GetResponseTrailerMode(), \"SEND\", \"GRPC\")\n\t}\n\treturn nil\n}\n\nfunc (builder) ParseFilterConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {\n\tm, ok := cfg.(*anypb.Any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"extproc: error parsing config %v: unknown type %T, want *anypb.Any\", cfg, cfg)\n\t}\n\tmsg := new(v3procfilterpb.ExternalProcessor)\n\tif err := m.UnmarshalTo(msg); err != nil {\n\t\treturn nil, fmt.Errorf(\"extproc: failed to unmarshal config %v: %v\", cfg, err)\n\t}\n\tif msg.GetProcessingMode() == nil {\n\t\treturn nil, fmt.Errorf(\"extproc: missing processing_mode in config %v\", cfg)\n\t}\n\tif err := validateBodyProcessingMode(msg.GetProcessingMode()); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif msg.GetGrpcService() == nil {\n\t\treturn nil, fmt.Errorf(\"extproc: empty grpc_service provided in config %v\", cfg)\n\t}\n\tserver, err := iextproc.ParseGRPCServiceConfig(msg.GetGrpcService())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"extproc: failed to parse grpc_service %v\", err)","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/httpfilter/extproc/ext_proc.go#L94-L130","documentation":"Returned by ParseFilterConfig when the proto.Message passed in is not *anypb.Any. The xDS resolver is expected to deliver filter configs as packed Any messages; receiving another type indicates an internal wiring bug in how the filter registry invokes the builder. Hit at ext_proc.go:111.","triggerScenarios":"Some internal caller invokes builder.ParseFilterConfig with a concrete *v3procfilterpb.ExternalProcessor (or any non-Any type) instead of *anypb.Any. End users essentially never trigger this directly; it surfaces during xDS resource parsing if the httpfilter registry contract is violated.","commonSituations":"A fork/patch of grpc-go changes the registry to pass unwrapped protos; a test harness constructs the wrong message type; an out-of-tree filter integration misuses the builder API.","solutions":["Ensure the caller wraps the config in *anypb.Any (anypb.New(msg)) before invoking ParseFilterConfig.","If you maintain a fork, re-check the httpfilter.Builder contract: config arrives as *anypb.Any.","Reproduce with the stock grpc-go resolver; if it works, the bug is in your integration code.","File a grpc-go issue if this occurs with unmodified grpc-go."],"exampleFix":"// before (internal caller)\ncfg, err := b.ParseFilterConfig(extProcMsg)\n// after\nanyCfg, _ := anypb.New(extProcMsg)\ncfg, err := b.ParseFilterConfig(anyCfg)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// internal caller: ensure you hand the builder an *anypb.Any\nfunc isAny(m proto.Message) bool {\n  _, ok := m.(*anypb.Any)\n  return ok\n}","tryCatchPattern":null,"preventionTips":["Always wrap configs in anypb.New before calling ParseFilterConfig.","Respect the httpfilter.Builder contract (input is *anypb.Any).","If this fires in stock grpc-go, file an issue.","Pin and audit forks that touch the filter registry."],"tags":["grpc","xds","extproc","internal","config"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}