grpc/grpc-go · error
RLS response's target list does not contain any entries for
Error message
RLS response's target list does not contain any entries for key %+v
What it means
When the RLS server returns an OK status but an empty targets list, the RLS protocol considers the response a failure (a successful response must name at least one backend target). handleRouteLookupResponse synthesizes this error and, because err != nil, puts the cache entry into backoff instead of installing targets. It is an internal/control-plane condition surfaced through backoff and metrics, not normally thrown directly at the caller.
Source
Thrown at balancer/rls/picker.go:320
// - status is set to error returned from the control channel
// - current backoff state is available in the pending entry
// - `retries` field is incremented and
// - backoff state is moved to the data cache
// - backoffTime is set to the time indicated by the backoff state
// - backoffExpirationTime is set to twice the backoff time
// - backoffTimer is set to fire after backoffTime
//
// When a proactive cache refresh fails, this would leave the targets and the
// expiry time from the old entry unchanged. And this mean that the old valid
// entry would be used until expiration, and a new picker would be sent upon
// backoff expiry.
now := time.Now()
// "An RLS request is considered to have failed if it returns a non-OK
// status or the RLS response's targets list is non-empty." - RLS LB Policy
// design.
if len(targets) == 0 && err == nil {
err = fmt.Errorf("RLS response's target list does not contain any entries for key %+v", cacheKey)
// If err is set, rpc error from the control plane and no control plane
// configuration is why no targets were passed into this helper, no need
// to specify and tell the user this information.
}
if err != nil {
dcEntry.status = err
pendingEntry := p.lb.pendingMap[cacheKey]
pendingEntry.retries++
backoffTime := pendingEntry.bs.Backoff(pendingEntry.retries)
dcEntry.backoffState = pendingEntry
dcEntry.backoffTime = now.Add(backoffTime)
dcEntry.backoffExpiryTime = now.Add(2 * backoffTime)
if dcEntry.backoffState.timer != nil {
dcEntry.backoffState.timer.Stop()
}
dcEntry.backoffState.timer = time.AfterFunc(backoffTime, p.lb.sendNewPicker)
return
}View on GitHub (pinned to 03255a9237)
Solutions
- Configure a defaultTarget in RouteLookupConfig so the RLS balancer falls back gracefully when this happens (useDefaultPickIfPossible).
- On the server side, verify the RLS key -> target mapping covers the keys your key builders emit.
- Inspect RLS server logs/metrics to confirm which key is returning no targets, then add the mapping.
Example fix
// before
"routeLookupConfig": { "lookupService": "rls:443", /* no defaultTarget */ }
// after
"routeLookupConfig": { "lookupService": "rls:443", "defaultTarget": "fallback-cluster" } Defensive patterns
Strategy: fallback
Validate before calling
func hasDefaultTarget(cfg *rlspb.RouteLookupConfig) bool {
return cfg.GetDefaultTarget() != ""
} Prevention
- Always set a defaultTarget in RouteLookupConfig so empty-target responses degrade gracefully.
- Verify the RLS server has key->target mappings for every key your key builders emit.
- Monitor RLS backoff and failed-pick metrics to catch empty-target responses early.
When it happens
Trigger: The RLS control plane accepts the RouteLookup RPC, returns OK with status nil, but the targets array in the response is empty (or the control channel dropped targets on the floor). Repeats trigger backoff and default-target fallback.
Common situations: RLS server misconfiguration (no mapping for the key); key builder producing keys the server does not recognize; partial rollout where the RLS data plane is up but its config is empty; the server returning headerData but no targets.
Related errors
- rls: method name %q is not of the form '/service/method
- xds: CertificateProvider to fetch trusted roots is missing,
- xds: CertificateProvider to fetch identity certificate is mi
- ringhash: expected xDS config selector to set the request ha
- rls: json unmarshal failed for service config %+v: %v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/14b961b078af0c91.
Report an issue: GitHub.