• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20266
89%

Build:
DEFAULT BRANCH: master
Ran 06 May 2026 05:47AM UTC
Jobs 1
Files 652
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

06 May 2026 05:34AM UTC coverage: 88.829% (-0.008%) from 88.837%
#20266

push

github

web-flow
xds: skip DiscoveryRequest for unsubscribed types on stream ready (#12782)

## TL;DR

When the bootstrap declares more than one xDS server (e.g. a default
server for LDS/CDS plus an authority-specific EDS-only server),
grpc-java was sending CDS/LDS DiscoveryRequests to the EDS-only server
too. That server replies `UNIMPLEMENTED`, which tears down the stream
and EDS data never arrives. Fix: skip DiscoveryRequests for resource
types we don't actually subscribe to on a given server.

## Problem

Under [A47 — xDS
Federation](https://github.com/grpc/proposal/blob/master/A47-xds-federation.md),
authorities can declare their own `xds_servers` block in the bootstrap.
When an ADS stream is opened to an authority-specific server,
`ControlPlaneClient.adjustResourceSubscription` sends a
`DiscoveryRequest` for every **globally-subscribed** resource type —
even types that have no subscription for *this* server. The empty
request still carries a `type_url`, and an authority-specific server
(e.g. an EDS-only control plane) may reject it with `UNIMPLEMENTED`,
which tears down the entire stream before the legitimate request that
follows can complete.

## Reproduce

Bootstrap declares two servers — call them control-plane-A (handles
LDS/CDS for authority A) and control-plane-B (handles EDS only for
authority B).

A grpc-java channel that resolves through LDS → CDS in authority A and
EDS in authority B opens an ADS stream to control-plane-B. When that
stream becomes ready,
[`sendDiscoveryRequests`](https://github.com/grpc/grpc-java/blob/master/xds/src/main/java/io/grpc/xds/client/ControlPlaneClient.java)
iterates `resourceStore.getSubscribedResourceTypesWithTypeUrl()` — which
returns **all three** types (Listener, Cluster, Endpoint) — and calls
`adjustResourceSubscription` for each. For Listener and Cluster,
`getSubscribedResources(serverInfo, type)` returns null/empty, but the
request is still sent on the wire:

```
io.grpc.StatusRuntimeException: UNAVAILABLE: Error ret... (continued)

36155 of 40702 relevant lines covered (88.83%)

0.89 hits per line

Coverage Regressions

Lines Coverage ∆ File
11
92.99
-0.82% ../xds/src/main/java/io/grpc/xds/client/ControlPlaneClient.java
6
74.14
-5.17% ../servlet/src/main/java/io/grpc/servlet/ServletServerStream.java
1
87.6
-0.83% ../rls/src/main/java/io/grpc/rls/LinkedHashLruCache.java
Jobs
ID Job ID Ran Files Coverage
1 #20266.1 06 May 2026 05:47AM UTC 652
88.83
Source Files on build #20266
  • Tree
  • List 652
  • Changed 7
  • Source Changed 0
  • Coverage Changed 7
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • Github Actions Build #20266
  • 53461b62 on github
  • Prev Build on master
  • Next Build on master
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc