grpc/grpc-go · error
extproc: failed to unmarshal config %v: %v
Error message
extproc: failed to unmarshal config %v: %v
What it means
Raised by ParseFilterConfig (ext_proc.go:116) when the ExternalProcessor Any's bytes cannot be deserialized into envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor. The ext_proc counterpart to error 360: structurally invalid wire data for the declared type causes the LDS resource to be NACKed.
Source
Thrown at internal/xds/httpfilter/extproc/ext_proc.go:116
return fmt.Errorf("extproc: invalid request body mode %v: want %q or %q", m, "NONE", "GRPC")
}
if m := mode.GetResponseBodyMode(); m != v3procfilterpb.ProcessingMode_NONE && m != v3procfilterpb.ProcessingMode_GRPC {
return fmt.Errorf("extproc: invalid response body mode %v: want %q or %q", m, "NONE", "GRPC")
}
if mode.GetResponseBodyMode() == v3procfilterpb.ProcessingMode_GRPC && mode.GetResponseTrailerMode() != v3procfilterpb.ProcessingMode_SEND {
return fmt.Errorf("extproc: invalid response trailer mode %v: must be %q when response body mode is %q", mode.GetResponseTrailerMode(), "SEND", "GRPC")
}
return nil
}
func (builder) ParseFilterConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {
m, ok := cfg.(*anypb.Any)
if !ok {
return nil, fmt.Errorf("extproc: error parsing config %v: unknown type %T, want *anypb.Any", cfg, cfg)
}
msg := new(v3procfilterpb.ExternalProcessor)
if err := m.UnmarshalTo(msg); err != nil {
return nil, fmt.Errorf("extproc: failed to unmarshal config %v: %v", cfg, err)
}
if msg.GetProcessingMode() == nil {
return nil, fmt.Errorf("extproc: missing processing_mode in config %v", cfg)
}
if err := validateBodyProcessingMode(msg.GetProcessingMode()); err != nil {
return nil, err
}
if msg.GetGrpcService() == nil {
return nil, fmt.Errorf("extproc: empty grpc_service provided in config %v", cfg)
}
server, err := iextproc.ParseGRPCServiceConfig(msg.GetGrpcService())
if err != nil {
return nil, fmt.Errorf("extproc: failed to parse grpc_service %v", err)
}
mutationRules, err := httpfilter.HeaderMutationRulesFromProto(msg.GetMutationRules())
if err != nil {View on GitHub (pinned to 03255a9237)
Solutions
- Read the wrapped %v for the protobuf-level cause (unexpected EOF = truncation; unknown field = version skew).
- Confirm type_url is 'type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor' and the body decodes as that exact message.
- Decode Any.value with protoc against the v3 ExternalProcessor descriptor; re-emit a correct resource.
Example fix
// before: Any payload is not a valid ExternalProcessor
//
// after: marshal the real v3 ExternalProcessor into the Any
import (
"google.golang.org/protobuf/types/known/anypb"
v3procfilterpb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_proc/v3"
)
ep := &v3procfilterpb.ExternalProcessor{
GrpcService: &v3corepb.GrpcService{ /* google_grpc... */ },
ProcessingMode: &v3procfilterpb.ProcessingMode{ /* NONE/GRPC only */ },
}
anyCfg, err := anypb.New(ep) Defensive patterns
Strategy: validation
Validate before calling
// Validate an ExternalProcessor Any before publishing (ext_proc.go:114-116).
func validateExtProcAny(a *anypb.Any) error {
if a == nil || a.TypeUrl != "type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor" {
return fmt.Errorf("wrong/nil type_url for ExternalProcessor")
}
msg := new(v3procfilterpb.ExternalProcessor)
if err := a.UnmarshalTo(msg); err != nil {
return fmt.Errorf("ExternalProcessor payload invalid: %w", err)
}
return nil
} Prevention
- Build ext_proc configs with anypb.New so type_url and payload agree.
- Match go-control-plane/envoy proto versions between control plane and client.
- Decode Any.value with protoc in CI before publishing.
When it happens
Trigger: cfg is a valid *anypb.Any but m.UnmarshalTo(new(v3procfilterpb.ExternalProcessor)) at ext_proc.go:115 returns a non-nil error — corrupt/truncated bytes, or payload serialized from a different message than the type_url claims.
Common situations: Control plane emitted a malformed ExternalProcessor config; type_url says ExternalProcessor but the body is a different proto; v2/v3 or go-control-plane version mismatch.
Related errors
- rls_csp: error parsing config %v: %v
- extauthz: failed to unmarshal config: %v
- extauthz: failed to unmarshal override config %v: %v
- extproc: invalid request body mode %v: want %q or %q
- extproc: invalid response body mode %v: want %q or %q
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/b7495d130a375bc2.
Report an issue: GitHub.