grpc/grpc-java · error · ResourceInvalidException
HttpConnectionManager contains invalid HttpFilter
Error message
HttpConnectionManager contains invalid HttpFilter: ${filterConfig.getErrorDetail()} What it means
One of the HttpFilter entries in the HttpConnectionManager failed to parse: parseHttpFilter returned a StructOrError carrying an error detail (unknown filter type, invalid typed_config, unsupported config). XdsListenerResource surfaces that error detail as a ResourceInvalidException prefixed with 'HttpConnectionManager contains invalid HttpFilter:'.
Solutions
- Read the embedded errorDetail in the message to identify which filter and field failed, then fix that filter's typed_config.
- Remove filters unsupported by gRPC xDS (keep only router and other registered gRPC filters); do Envoy-specific filtering at the Envoy proxy.
- Verify the filter's @type URL and config schema against the gRPC version in use; upgrade the library if the filter should be supported.
Example fix
// before: Envoy-only filter gRPC cannot parse
http_filters:
- name: envoy.filters.http.lua
typed_config: { "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua, ... }
// after
http_filters:
- name: envoy.filters.http.router
typed_config: { "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router } Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check each filter against the registry before submission
for (HttpFilter f : hcm.getHttpFiltersList()) {
if (!KNOWN_GRPC_HTTP_FILTERS.contains(f.getName()))
throw new IllegalArgumentException("filter not supported by grpc xds: " + f.getName());
} Try / catch
try { applyResource(listener) } catch (ResourceInvalidException e) { if (e.getMessage().startsWith("HttpConnectionManager contains invalid HttpFilter")) { logDetail(e.getMessage()); dropUnparsableFiltersAndResubmit(); } } Prevention
- Restrict http_filters to filters registered with gRPC xDS (primarily the router filter)
- Validate typed_config @type URLs and schemas against the gRPC version
- Parse the errorDetail embedded in the message to pinpoint the failing filter quickly
When it happens
Trigger: During the http_filters loop in parseHttpConnectionManager, filterConfig.getErrorDetail() != null — i.e. the filter's typed_config references an unknown filter name, has a malformed Any/Struct config, or the filter's own config parser rejected the values.
Common situations: Filters the gRPC filter registry does not recognize (Envoy-only filters like http lua or ext_proc), typed_config @type URLs that don't match the registered filter, or config fields invalid for the specific filter version.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- HttpConnectionManager contains duplicate HttpFilter
- HttpConnectionManager with original_ip_detection_extensions…
- HttpConnectionManager with xff_num_trusted_hops unsupported
- Missing HttpFilter in HttpConnectionManager.
- The last HttpFilter must be a terminal filter
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/c8fd58266450f267.
Report an issue: GitHub.
Appendix: source
Thrown at xds/src/main/java/io/grpc/xds/XdsListenerResource.java:540
io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter
httpFilter = proto.getHttpFiltersList().get(i);
String filterName = httpFilter.getName();
if (!names.add(filterName)) {
throw new ResourceInvalidException(
"HttpConnectionManager contains duplicate HttpFilter: " + filterName);
}
StructOrError<Filter.FilterConfig> filterConfig =
parseHttpFilter(httpFilter, filterRegistry, isForClient, args);
if ((i == proto.getHttpFiltersCount() - 1)
&& (filterConfig == null || !isTerminalFilter(filterConfig.getStruct()))) {
throw new ResourceInvalidException("The last HttpFilter must be a terminal filter: "
+ filterName);
}
if (filterConfig == null) {
continue;
}
if (filterConfig.getErrorDetail() != null) {
throw new ResourceInvalidException(
"HttpConnectionManager contains invalid HttpFilter: "
+ filterConfig.getErrorDetail());
}
if ((i < proto.getHttpFiltersCount() - 1) && isTerminalFilter(filterConfig.getStruct())) {
throw new ResourceInvalidException("A terminal HttpFilter must be the last filter: "
+ filterName);
}
filterConfigs.add(new Filter.NamedFilterConfig(filterName, filterConfig.getStruct()));
}
// Parse inlined RouteConfiguration or RDS.
if (proto.hasRouteConfig()) {
List<VirtualHost> virtualHosts = extractVirtualHosts(
proto.getRouteConfig(), filterRegistry, args);
return io.grpc.xds.HttpConnectionManager.forVirtualHosts(
maxStreamDuration, virtualHosts, filterConfigs);
}
if (proto.hasRds()) {View on GitHub (pinned to 64daddc1f3)