{"record":{"id":"d15ef9a637c96778","repo":"grpc/grpc-go","slug":"extauthz-error-parsing-override-config-v-unknow","errorCode":null,"errorMessage":"extauthz: error parsing override config %v: unknown type %T, want *anypb.Any","messagePattern":"extauthz: error parsing override config (.+?): unknown type %T, want \\*anypb\\.Any","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/ext_authz/ext_authz.go","lineNumber":172,"sourceCode":"\t\tfailureModeAllowHeaderAdd:  msg.GetFailureModeAllowHeaderAdd(),\n\t\tstatusOnError:              statusOnError,\n\t\tallowedHeaders:             allowedHeaders,\n\t\tdisallowedHeaders:          disallowedHeaders,\n\t\tdecoderHeaderMutationRules: mutationRules,\n\t\tincludePeerCertificate:     msg.GetIncludePeerCertificate(),\n\t}, nil\n}\n\n// ParseFilterConfigOverride parses the provided override configuration.\n//\n// Note that ExtAuthzPerRoute is unmarshaled to verify its syntax during xDS\n// resource validation, no filter configuration object is returned. Per-route\n// disabling is supported via the generic FilterConfig wrapper mechanism rather\n// than the ExtAuthzPerRoute.disabled field directly.\nfunc (builder) ParseFilterConfigOverride(overrideCfg proto.Message) (httpfilter.FilterConfig, error) {\n\tm, ok := overrideCfg.(*anypb.Any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"extauthz: error parsing override config %v: unknown type %T, want *anypb.Any\", overrideCfg, overrideCfg)\n\t}\n\tmsg := new(v3extauthzpb.ExtAuthzPerRoute)\n\tif err := m.UnmarshalTo(msg); err != nil {\n\t\treturn nil, fmt.Errorf(\"extauthz: failed to unmarshal override config %v: %v\", overrideCfg, err)\n\t}\n\treturn nil, nil\n}\n\nfunc (builder) IsTerminal() bool {\n\treturn false\n}\n","sourceCodeStart":154,"sourceCodeEnd":184,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/httpfilter/ext_authz/ext_authz.go#L154-L184","documentation":"Raised by ParseFilterConfigOverride (ext_authz.go:172) when the per-route override message passed in is not an *anypb.Any. The builder contract (httpfilter.go:60) wraps typed filter configs in *anypb.Any, so a non-Any indicates the xDS decoding layer supplied the wrong concrete type for an ExtAuthzPerRoute override.","triggerScenarios":"The xDS resolver calls builder.ParseFilterConfigOverride(overrideCfg) where overrideCfg is a proto.Message that is not *anypb.Any (the type assertion at ext_authz.go:170 fails). This is an internal/xDS-decoder contract violation rather than something an end user's YAML directly controls.","commonSituations":"A gRPC/xDS resolver change that passes a raw typed struct (e.g. TypedStruct or the already-unmarshaled ExtAuthzPerRoute) instead of the wrapping Any; a test harness that calls ParseFilterConfigOverride directly with the wrong type; version skew between the resolver and the filter builder.","solutions":["If you are calling ParseFilterConfigOverride directly (tests/tools), wrap your message with anypb.New before passing it.","If this surfaces in production, it indicates a resolver/builder version mismatch — update gRPC-Go so the resolver and this filter package agree on the *anypb.Any contract.","Confirm the per-route typed_per_filter_config entry uses the ExtAuthzPerRoute type URL so the resolver keeps it wrapped as an Any."],"exampleFix":"// before (test / direct call): passing the raw message\n//   fc, err := b.ParseFilterConfigOverride(perRoute) // perRoute is *v3extauthzpb.ExtAuthzPerRoute\n//\n// after: wrap in *anypb.Any\nanyOv, err := anypb.New(perRoute)\nif err != nil { return err }\nfc, err := b.ParseFilterConfigOverride(anyOv)","handlingStrategy":"type-guard","validationCode":"// Guarantee the override is wrapped as *anypb.Any before handing it to\n// ParseFilterConfigOverride (ext_authz.go:170).\nfunc wrapOverride(m proto.Message) (*anypb.Any, error) {\n    if a, ok := m.(*anypb.Any); ok {\n        return a, nil\n    }\n    return anypb.New(m)\n}","typeGuard":"func isAny(m proto.Message) (*anypb.Any, bool) {\n    a, ok := m.(*anypb.Any)\n    return a, ok\n}","tryCatchPattern":null,"preventionTips":["When calling filter builders directly, always pass *anypb.Any, never the bare proto.","Keep the xDS resolver and the filter builder from the same gRPC-Go version so the Any contract holds.","In tests, use a helper that wraps every override via anypb.New."],"tags":["grpc","xds","config","ext-authz","type-assertion"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}