{"record":{"id":"c79d987df9e7e1c7","repo":"grpc/grpc-java","slug":"httpconnectionmanager-contains-invalid-rds-missin","errorCode":null,"errorMessage":"HttpConnectionManager contains invalid RDS: missing config_source","messagePattern":"HttpConnectionManager contains invalid RDS: missing config_source","errorType":"exception","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/XdsListenerResource.java","lineNumber":561,"sourceCode":"      }\n      if ((i < proto.getHttpFiltersCount() - 1) && isTerminalFilter(filterConfig.getStruct())) {\n        throw new ResourceInvalidException(\"A terminal HttpFilter must be the last filter: \"\n            + filterName);\n      }\n      filterConfigs.add(new Filter.NamedFilterConfig(filterName, filterConfig.getStruct()));\n    }\n\n    // Parse inlined RouteConfiguration or RDS.\n    if (proto.hasRouteConfig()) {\n      List<VirtualHost> virtualHosts = extractVirtualHosts(\n          proto.getRouteConfig(), filterRegistry, args);\n      return io.grpc.xds.HttpConnectionManager.forVirtualHosts(\n          maxStreamDuration, virtualHosts, filterConfigs);\n    }\n    if (proto.hasRds()) {\n      Rds rds = proto.getRds();\n      if (!rds.hasConfigSource()) {\n        throw new ResourceInvalidException(\n            \"HttpConnectionManager contains invalid RDS: missing config_source\");\n      }\n      if (!rds.getConfigSource().hasAds() && !rds.getConfigSource().hasSelf()) {\n        throw new ResourceInvalidException(\n            \"HttpConnectionManager contains invalid RDS: must specify ADS or self ConfigSource\");\n      }\n      return io.grpc.xds.HttpConnectionManager.forRdsName(\n          maxStreamDuration, rds.getRouteConfigName(), filterConfigs);\n    }\n    throw new ResourceInvalidException(\n        \"HttpConnectionManager neither has inlined route_config nor RDS\");\n  }\n\n  // hard-coded: currently router config is the only terminal filter.\n  private static boolean isTerminalFilter(Filter.FilterConfig filterConfig) {\n    return RouterFilter.ROUTER_CONFIG.equals(filterConfig);\n  }\n","sourceCodeStart":543,"sourceCodeEnd":579,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/XdsListenerResource.java#L543-L579","documentation":"An HttpConnectionManager configured with RDS (route discovery service) must supply a config_source telling gRPC where to discover the RouteConfiguration. When the Rds message has no config_source set at all, xDS resource parsing fails with ResourceInvalidException and the listener is rejected.","triggerScenarios":"parseHttpConnectionManager sees proto.hasRds() true but rds.hasConfigSource() false — i.e. an Rds block with only a route_config_name and no config_source field.","commonSituations":"Envoy listener config omitting config_source under rds; YAML-to-proto conversion dropping the nested field; hand-crafted RDS blocks copied from examples that used ADS implicitly in Envoy but must be explicit here.","solutions":["Add a config_source to the Rds block, e.g. ads: {} for ADS-based discovery","Alternatively use config_source { self: {} } for the same management server","If routes are static, inline a route_config in the HttpConnectionManager instead of using RDS"],"exampleFix":"// before\nrds: { route_config_name: \"routes\" }\n// after\nrds: {\n  route_config_name: \"routes\"\n  config_source: { ads: {} }\n}","handlingStrategy":"validation","validationCode":"// Java (proto): check RDS completeness before applying\nif (hcm.hasRds() && !hcm.getRds().hasConfigSource()) {\n  throw new IllegalArgumentException(\"rds requires config_source (e.g. ads: {})\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  xdsClient.watchResource(LISTENER, name, listenerWatcher);\n} catch (ResourceInvalidException e) {\n  if (e.getMessage().contains(\"missing config_source\")) {\n    log.error(\"RDS block lacks config_source; fix control plane template\");\n  }\n}","preventionTips":["Template RDS blocks with config_source { ads: {} } by default","Lint listener configs for required RDS subfields","Diff generated protos against a known-good sample"],"tags":["xds","grpc","rds","config-validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}