grpc/grpc-go · error
extproc: error parsing override %v: unknown type %T, want *a
Error message
extproc: error parsing override %v: unknown type %T, want *anypb.Any
What it means
Raised by ParseFilterConfigOverride when the per-route override proto passed to the extproc filter builder is not a *anypb.Any. The XDS layer is expected to always hand the filter a decoded *anypb.Any; this assertion enforces that contract. Hitting it means the data path feeding filter overrides deviated from the registered type-URL contract.
Source
Thrown at internal/xds/httpfilter/extproc/ext_proc.go:176
return baseConfig{
processingModes: processingModesFromProto(msg.GetProcessingMode()),
requestAttributes: msg.GetRequestAttributes(),
responseAttributes: msg.GetResponseAttributes(),
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())View on GitHub (pinned to 03255a9237)
Solutions
- Wrap the per-route override message in *anypb.Any before passing it to ParseFilterConfigOverride: anypb.New(&v3procfilterpb.ExtProcPerRoute{...}).
- If this surfaces from real xDS traffic, verify the LDS route configuration encodes typed_per_filter_config as a typed Struct/Any with @type set to type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute.
- Check that no other httpfilter.Register call shadowed extproc's builder, which can corrupt type dispatch.
Example fix
// before
m := &v3procfilterpb.ExtProcPerRoute{Overrides: &v3procfilterpb.ExtProcPerRoute_Overrides{...}}
cfg, err := builder{}.ParseFilterConfigOverride(m)
// after
a, _ := anypb.New(&v3procfilterpb.ExtProcPerRoute{Overrides: &v3procfilterpb.ExtProcPerRoute_Overrides{...}})
cfg, err := builder{}.ParseFilterConfigOverride(a) Defensive patterns
Strategy: type-guard
Validate before calling
// The XDS layer should always pass *anypb.Any; guard in code that wraps the builder.
func safeParseOverride(b httpfilter.FilterBuilder, ov proto.Message) (httpfilter.FilterConfig, error) {
if _, ok := ov.(*anypb.Any); !ok {
return nil, fmt.Errorf("override must be *anypb.Any, got %T", ov)
}
return b.ParseFilterConfigOverride(ov)
} Type guard
func isAny(m proto.Message) bool { _, ok := m.(*anypb.Any); return ok } Prevention
- Always wrap per-route overrides with anypb.New before invoking ParseFilterConfigOverride in tests.
- Keep typed_per_filter_config entries keyed by filter name so the registry dispatches the right builder.
When it happens
Trigger: ParseFilterConfigOverride is called (during LDS/xDS resource decoding) with a proto.Message whose concrete type is not *anypb.Any — e.g. a test invoking the builder directly with a *v3procfilterpb.ExtProcPerRoute instead of wrapping it in an Any, or a non-conformant custom httpfilter plumbing that forwards the unwrapped message.
Common situations: Unit/integration tests that call ParseFilterConfigOverride directly without wrapping the override in anypb.New(). A forked or custom xDS client that decodes typed_per_filter_config into the inner message type before handing it to the builder. A filter-registry bug that re-dispatches the wrong concrete type.
Related errors
- extproc: failed to unmarshal override %v: %v
- extproc: failed to parse grpc_service: %v
- extproc: incorrect config type provided (%T): %v
- extproc: incorrect override config type provided (%T): %v
- lrs: unexpected message type %T
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/5d3938a54bea0115.
Report an issue: GitHub.