{"record":{"id":"294cd0801a466108","repo":"grpc/grpc-go","slug":"extproc-empty-grpc-service-provided-in-config-v","errorCode":null,"errorMessage":"extproc: empty grpc_service provided in config %v","messagePattern":"extproc: empty grpc_service provided in config (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/extproc/ext_proc.go","lineNumber":126,"sourceCode":"\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)\n\t}\n\n\tmutationRules, err := httpfilter.HeaderMutationRulesFromProto(msg.GetMutationRules())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar allowedHeaders, disallowedHeaders []matcher.StringMatcher\n\tif allowed := msg.GetForwardRules().GetAllowedHeaders(); allowed != nil {\n\t\tallowedHeaders, err = httpfilter.ConvertStringMatchers(allowed.GetPatterns())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/httpfilter/extproc/ext_proc.go#L108-L144","documentation":"Raised by ParseFilterConfig (ext_proc.go:126) when the ExternalProcessor config unmarshals and has a processing_mode but no grpc_service. ext_proc needs a backend gRPC stream to the external processor; without a grpc_service the filter cannot operate, so the resource is rejected.","triggerScenarios":"msg.GetGrpcService() == nil at ext_proc.go:125, i.e. the ExternalProcessor proto was provided with a processing_mode but the grpc_service field was not set.","commonSituations":"A config that defines processing_mode but forgets grpc_service; a templating condition that drops the grpc_service block; partial config during rollout.","solutions":["Add a grpc_service block (google_grpc with a non-empty target_uri) to the ExternalProcessor config.","Ensure the same grpc_service parses cleanly (google_grpc, concrete target) so you do not then hit error 379.","Re-apply the LDS resource and verify the client ACKs it."],"exampleFix":"// before\n//   external_processor: { processing_mode: { ... } }   // grpc_service missing -> error 378\n//\n// after\n//   external_processor: {\n//     grpc_service: { google_grpc: { target_uri: \"dns:///ext-proc.ns:9092\" } },\n//     processing_mode: { ... }\n//   }","handlingStrategy":"validation","validationCode":"// Ensure grpc_service is present (ext_proc.go:125-127).\nfunc ensureExtProcGrpcService(cfg *v3procfilterpb.ExternalProcessor) error {\n    if cfg.GetGrpcService() == nil {\n        return fmt.Errorf(\"extproc: grpc_service is required\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat grpc_service as required in every ext_proc control-plane template.","Provide processing_mode AND grpc_service together when authoring ext_proc filters.","Add a policy check rejecting ext_proc configs that omit grpc_service."],"tags":["grpc","xds","config","ext-proc","grpc-service"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}