grpc/grpc-go · error
extproc: failed to unmarshal override
Error message
extproc: failed to unmarshal override %v: %v
What it means
Returned by ParseFilterConfigOverride (ext_proc.go:180) when the per-route ExtProcPerRoute override carried in an xDS resource cannot be unmarshalled from its *anypb.Any wrapper. The filter rejects the route override and the xDS update is discarded. It means the control plane published a malformed or wrong-type override payload for the ext_proc HTTP filter.
Solutions
- Confirm the override *anypb.Any.type_url is exactly type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute.
- Align the control plane and the gRPC client on the same envoy/go-control-plane version so the ExtProcPerRoute schema matches.
- Dump the raw override bytes (GRPC_GO_XDS_DEBUG logs / management-server debug dump) and verify they decode as ExtProcPerRoute with protoc --decode_raw.
- Re-publish the LDS/RDS resource from the control plane after correcting the override payload.
Example fix
// before (control plane): override Any packed with the wrong message
any := &anypb.Any{TypeUrl: "type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute"}
any.MarshalAny(&envoyextensionsfiltershttpextprocv3.ExternalProcessor{}) // wrong type
// after: pack the correct per-route override type
perRoute := &envoyextensionsfiltershttpextprocv3.ExtProcPerRoute{
Override: &envoyextensionsfiltershttpextprocv3.ExtProcOverride{
ProcessingMode: &envoyextensionsfiltershttpextprocv3.ProcessingMode{},
},
}
any, _ := anypb.New(perRoute) // TypeUrl auto-set correctly Defensive patterns
Strategy: validation
Validate before calling
// Before publishing an xDS override, confirm the Any is a valid ExtProcPerRoute.
func validateExtProcOverrideAny(a *anypb.Any) error {
const want = "type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute"
if a == nil || a.TypeUrl != want {
return fmt.Errorf("override type_url=%q want %q", a.GetTypeUrl(), want)
}
var m envoyextensionsfiltershttpextprocv3.ExtProcPerRoute
return a.UnmarshalTo(&m) // returns error iff bytes are malformed
} Type guard
// Narrow an arbitrary proto.Message to the expected override type before parsing.
func isExtProcPerRouteAny(cfg proto.Message) (*anypb.Any, bool) {
a, ok := cfg.(*anypb.Any)
if !ok {
return nil, false
}
return a, a.TypeUrl == "type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute"
} Try / catch
// In control-plane test: assert ParseFilterConfigOverride rejects bad overrides fast.
if _, err := builder{}.ParseFilterConfigOverride(badAny); err != nil {
if strings.Contains(err.Error(), "failed to unmarshal override") {
// expected: reject before publishing
}
} Prevention
- Always construct overrides with anypb.New(&ExtProcPerRoute{...}) so the type_url is set automatically.
- Pin control-plane and client to the same go-control-plane module version.
- Add a CI step that round-trips every published override through ParseFilterConfigOverride.
- Enable GRPC_GO_XDS_DEBUG logging in staging to catch malformed overrides early.
When it happens
Trigger: Triggered while parsing an HttpFilter typed_config_override of the ext_proc type URL whose *anypb.Any value either has the wrong type_url or is not a validly-encoded envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute message (m.UnmarshalTo(msg) at ext_proc.go:179 fails).
Common situations: Control-plane/client proto revision mismatch (server ships an override schema the client's go-control-plane does not recognize), wrong type_url stamped on the Any, a hand-rolled xDS server packing the wrong message into the override, or truncated/corrupt override bytes from a misconfigured management server.
Related errors
- extproc: failed to parse grpc_service
- extproc: failed to unmarshal config
- extproc: response message does not implement proto.Message
- external processor returned invalid body mutation in body…
- external processor returned unexpected status
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/1eebc6c63f261c27.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/httpfilter/extproc/ext_proc.go:180
disableImmediateResponse: msg.GetDisableImmediateResponse(),
observabilityMode: msg.GetObservabilityMode(),
failureModeAllow: msg.GetFailureModeAllow(),
server: server,
mutationRules: mutationRules,
allowedHeaders: allowedHeaders,
disallowedHeaders: disallowedHeaders,
deferredCloseTimeout: deferredCloseTimeout,
}, nil
}
func (builder) ParseFilterConfigOverride(ov proto.Message) (httpfilter.FilterConfig, error) {
m, ok := ov.(*anypb.Any)
if !ok {
return nil, fmt.Errorf("extproc: error parsing override %v: unknown type %T, want *anypb.Any", ov, ov)
}
msg := new(v3procfilterpb.ExtProcPerRoute)
if err := m.UnmarshalTo(msg); err != nil {
return nil, fmt.Errorf("extproc: failed to unmarshal override %v: %v", ov, err)
}
override := msg.GetOverrides()
var processingModesOpt optional.Optional[processingModes]
if pm := override.GetProcessingMode(); pm != nil {
if err := validateBodyProcessingMode(pm); err != nil {
return nil, err
}
processingModesOpt = optional.New(processingModesFromProto(pm))
}
var serverOpt optional.Optional[xdsresource.GRPCServiceConfig]
if override.GetGrpcService() != nil {
server, err := iextproc.ParseGRPCServiceConfig(override.GetGrpcService())
if err != nil {
return nil, fmt.Errorf("extproc: failed to parse grpc_service: %v", err)
}
serverOpt = optional.New(server)View on GitHub (pinned to 0c51461d27)