grpc/grpc-java · error · ResourceInvalidException
HttpConnectionManager contains invalid RDS: must specify…
Error message
HttpConnectionManager contains invalid RDS: must specify ADS or self ConfigSource
What it means
When an HttpConnectionManager uses RDS, the config_source must specify either ADS or SELF as the discovery mechanism. A config_source pointing at a non-ADS, non-SELF source (e.g. a path-based or gRPC API source) is rejected because this gRPC xDS implementation only supports ADS or self discovery for route configurations.
Solutions
- Change the Rds config_source to ads: {}
- Or use config_source { self: {} } if the listener and routes come from the same server
- Ensure the client connects over ADS (grpc xDS bootstrap with ADS servers) so the source is valid
Example fix
// before
rds: {
route_config_name: "routes"
config_source: { path: "/etc/envoy/routes.pb" }
}
// after
rds: {
route_config_name: "routes"
config_source: { ads: {} }
} Defensive patterns
Strategy: validation
Validate before calling
// Java (proto): ensure config_source is ADS or SELF
Rds rds = hcm.getRds();
if (rds.hasConfigSource()
&& !rds.getConfigSource().hasAds()
&& !rds.getConfigSource().hasSelf()) {
throw new IllegalArgumentException("RDS config_source must be ads or self");
} Try / catch
try {
xdsClient.watchResource(LISTENER, name, listenerWatcher);
} catch (ResourceInvalidException e) {
log.error("Unsupported RDS config_source: {}", e.getMessage());
} Prevention
- Never reuse Envoy path/grpc-api config_source blocks in gRPC xDS configs
- Use ads: {} or self: {} exclusively for RDS config sources
- Keep the client's bootstrap configured for ADS
When it happens
Trigger: parseHttpConnectionManager: rds.hasConfigSource() is true but neither config_source.hasAds() nor config_source.hasSelf() is set (e.g. api_type GRPC or path-based config_source).
Common situations: Configs written for Envoy's file-based (path) config source or a separate gRPC management server being reused with gRPC xDS; copy-pasted Envoy bootstrap config_source blocks.
Related errors
- HttpConnectionManager contains invalid RDS: missing…
- A terminal HttpFilter must be the last filter
- Address is not an IP
- All xds transports for authority are in backoff
- AndMatcher must have at least 2 predicates
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/fa7afd22647a4206.
Report an issue: GitHub.
Appendix: source
Thrown at xds/src/main/java/io/grpc/xds/XdsListenerResource.java:565
}
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()) {
Rds rds = proto.getRds();
if (!rds.hasConfigSource()) {
throw new ResourceInvalidException(
"HttpConnectionManager contains invalid RDS: missing config_source");
}
if (!rds.getConfigSource().hasAds() && !rds.getConfigSource().hasSelf()) {
throw new ResourceInvalidException(
"HttpConnectionManager contains invalid RDS: must specify ADS or self ConfigSource");
}
return io.grpc.xds.HttpConnectionManager.forRdsName(
maxStreamDuration, rds.getRouteConfigName(), filterConfigs);
}
throw new ResourceInvalidException(
"HttpConnectionManager neither has inlined route_config nor RDS");
}
// hard-coded: currently router config is the only terminal filter.
private static boolean isTerminalFilter(Filter.FilterConfig filterConfig) {
return RouterFilter.ROUTER_CONFIG.equals(filterConfig);
}
@VisibleForTesting
@Nullable // Returns null if the filter is optional but not supported.
static StructOrError<Filter.FilterConfig> parseHttpFilter(
io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilterView on GitHub (pinned to 64daddc1f3)