grpc/grpc-java · error · ResourceInvalidException

ClusterLoadAssignment has duplicate locality:${locality} for

Error message

ClusterLoadAssignment has duplicate locality:${locality} for priority:${priority}

What it means

Within one priority level, each Locality in a ClusterLoadAssignment must be unique. If two LocalityLbEndpoints entries map to the same Locality (region/zone/sub_zone) at the same priority, processClusterLoadAssignment rejects the EDS resource with ResourceInvalidException.

Source

Thrown at xds/src/main/java/io/grpc/xds/XdsEndpointResource.java:144

        continue;
      }
      if (structOrError.getErrorDetail() != null) {
        throw new ResourceInvalidException(structOrError.getErrorDetail());
      }

      LocalityLbEndpoints localityLbEndpoints = structOrError.getStruct();
      int priority = localityLbEndpoints.priority();
      maxPriority = Math.max(maxPriority, priority);
      // Note endpoints with health status other than HEALTHY and UNKNOWN are still
      // handed over to watching parties. It is watching parties' responsibility to
      // filter out unhealthy endpoints. See EnvoyProtoData.LbEndpoint#isHealthy().
      Locality locality =  parseLocality(localityLbEndpointsProto.getLocality());
      localityLbEndpointsMap.put(locality, localityLbEndpoints);
      if (!priorities.containsKey(priority)) {
        priorities.put(priority, new HashSet<>());
      }
      if (!priorities.get(priority).add(locality)) {
        throw new ResourceInvalidException("ClusterLoadAssignment has duplicate locality:"
            + locality + " for priority:" + priority);
      }
    }
    if (priorities.size() != maxPriority + 1) {
      throw new ResourceInvalidException("ClusterLoadAssignment has sparse priorities");
    }

    for (ClusterLoadAssignment.Policy.DropOverload dropOverloadProto
        : assignment.getPolicy().getDropOverloadsList()) {
      dropOverloads.add(parseDropOverload(dropOverloadProto));
    }
    return new EdsUpdate(assignment.getClusterName(), localityLbEndpointsMap, dropOverloads);
  }

  private static Locality parseLocality(io.envoyproxy.envoy.config.core.v3.Locality proto) {
    return Locality.create(proto.getRegion(), proto.getZone(), proto.getSubZone());
  }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Deduplicate LocalityLbEndpoints entries by Locality key in the control plane
  2. Merge endpoints of duplicate localities into a single LocalityLbEndpoints entry
  3. Ensure locality labels (region/zone/sub_zone) are unique per priority in EDS output
  4. Add control-plane-side validation before sending EDS updates

Example fix

# before (same priority, duplicate locality)
- locality: {region: "us-east1", zone: "a"}
  priority: 0
- locality: {region: "us-east1", zone: "a"}
  priority: 0
# after
- locality: {region: "us-east1", zone: "a"}
  priority: 0
  endpoints: [all addresses]
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (LocalityLbEndpoints lle : assignment.getEndpointsList()) {
  String key = lle.getLocality().getRegion() + "/" + lle.getLocality().getZone()
      + "/" + lle.getLocality().getSubZone() + "@" + lle.getPriority();
  if (!seen.add(key)) throw new IllegalArgumentException("duplicate locality/priority: " + key);
}

Try / catch

try {
  update = XdsEndpointResource.getInstance().parse(args, resource);
} catch (ResourceInvalidException e) {
  logger.warn("EDS rejected: {}", e.getMessage());
}

Prevention

When it happens

Trigger: An EDS ClusterLoadAssignment lists two LocalityLbEndpoints with identical Locality (same region, zone, sub_zone) assigned the same priority value; detected when priorities.get(priority).add(locality) returns false.

Common situations: Management servers aggregating endpoint data from multiple sources and emitting duplicate locality entries; service-discovery backends returning overlapping locality labels; buggy EDS generators that split one locality across entries.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/be0d75ff92016872. Report an issue: GitHub.