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

  1. Confirm the override *anypb.Any.type_url is exactly type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute.
  2. Align the control plane and the gRPC client on the same envoy/go-control-plane version so the ExtProcPerRoute schema matches.
  3. Dump the raw override bytes (GRPC_GO_XDS_DEBUG logs / management-server debug dump) and verify they decode as ExtProcPerRoute with protoc --decode_raw.
  4. 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

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


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)