grpc/grpc-java · error · ResourceInvalidException
FilterChain ${filterChainName} should contain exact one Http
Error message
FilterChain ${filterChainName} should contain exact one HttpConnectionManager filter What it means
A server-side FilterChain must contain exactly one L4 filter, and that filter must be an HttpConnectionManager (HCM) typed config - gRPC xDS does not support arbitrary L4 filter stacks. When filters_count != 1, parseFilterChain throws ResourceInvalidException. This enforces the gRPC xDS server-side protocol contract.
Source
Thrown at xds/src/main/java/io/grpc/xds/XdsListenerResource.java:232
return EnvoyServerProtoData.Listener.create(proto.getName(), address, filterChains.build(),
defaultFilterChain, socketAddress == null ? null : socketAddress.getProtocol());
}
@VisibleForTesting
static FilterChain parseFilterChain(
io.envoyproxy.envoy.config.listener.v3.FilterChain proto,
String filterChainName,
TlsContextManager tlsContextManager,
FilterRegistry filterRegistry,
// null disables FilterChainMatch uniqueness check, used for defaultFilterChain
@Nullable Set<FilterChainMatch> filterChainMatchSet,
Set<String> certProviderInstances,
XdsResourceType.Args args)
throws ResourceInvalidException {
// FilterChain contains L4 filters, so we ensure it contains only HCM.
if (proto.getFiltersCount() != 1) {
throw new ResourceInvalidException("FilterChain " + filterChainName
+ " should contain exact one HttpConnectionManager filter");
}
io.envoyproxy.envoy.config.listener.v3.Filter l4Filter = proto.getFiltersList().get(0);
if (!l4Filter.hasTypedConfig()) {
throw new ResourceInvalidException(
"FilterChain " + filterChainName + " contains filter " + l4Filter.getName()
+ " without typed_config");
}
Any any = l4Filter.getTypedConfig();
if (!any.getTypeUrl().equals(TYPE_URL_HTTP_CONNECTION_MANAGER)) {
throw new ResourceInvalidException(
"FilterChain " + filterChainName + " contains filter " + l4Filter.getName()
+ " with unsupported typed_config type " + any.getTypeUrl());
}
// Parse HCM.
HttpConnectionManager hcmProto;
try {View on GitHub (pinned to 64daddc1f3)
Solutions
- Ensure each filter_chain contains exactly one filter whose typed_config is envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
- Remove extra filters from the filter chain and move them elsewhere if your control plane supports it
- Regenerate the LDS resource so the filters list is populated with a single HCM filter
Example fix
# before
filters: []
# after
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager Defensive patterns
Strategy: validation
Validate before calling
for (FilterChain fc : listener.getFilterChainsList()) {
if (fc.getFiltersCount() != 1) {
throw new IllegalArgumentException(
"FilterChain must contain exactly one filter, got " + fc.getFiltersCount());
}
} Try / catch
try {
listener = XdsListenerResource.parseServerSideListener(proto, ...);
} catch (ResourceInvalidException e) {
if (e.getMessage().contains("should contain exact one HttpConnectionManager")) {
logger.warn("LDS resource has malformed filters list", e);
}
} Prevention
- Model server-side filter chains as exactly one HCM filter in control-plane templates
- Validate LDS resources against the gRPC xDS schema before publishing
- Do not port multi-filter Envoy L4 stacks to gRPC xDS consumers
When it happens
Trigger: A FilterChain proto has zero filters, or more than one entry in its filters list, when parsed by parseFilterChain (reached from parseServerSideListener).
Common situations: Envoy configs copied verbatim that stack multiple filters (e.g. TLS inspector + HCM) inside one filter chain; control planes emitting empty filters lists; mis-generated protos omitting the HCM filter.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- unsupported ExtAuthz service type: only grpc_service is supp
- Invalid ring hash function: " + ringHash.getHashFunction()
- Custom LB config does not contain a JSON object
- Invalid header matcher config: [grpc-] prefixed header name
- Invalid header matcher config: header name [:scheme] is not
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/0362d85559679c7a.
Report an issue: GitHub.