grpc/grpc-java · error · ResourceInvalidException

Cluster " + cluster.getName() + ": unsupported lb policy: "

Error message

Cluster " + cluster.getName() + ": unsupported lb policy: " + cluster.getLbPolicy()

What it means

convertToServiceConfig maps an Envoy Cluster's lb_policy enum to a gRPC service config. Only ROUND_ROBIN, LEAST_REQUEST (when enabled) and their wrappers are supported; any other lb_policy (e.g. RANDOM, MAGLEV, CLUSTER_PROVIDED in this path) has no gRPC equivalent, so the resource is rejected as invalid.

Source

Thrown at xds/src/main/java/io/grpc/xds/LoadBalancerConfigFactory.java:422

     * Cluster}.
     *
     * @throws ResourceInvalidException If the {@link Cluster} has an invalid LB configuration.
     */
    static ImmutableMap<String, ?> convertToServiceConfig(Cluster cluster,
        boolean enableLeastRequest) throws ResourceInvalidException {
      switch (cluster.getLbPolicy()) {
        case RING_HASH:
          return convertRingHashConfig(cluster);
        case ROUND_ROBIN:
          return buildWrrLocalityConfig(buildRoundRobinConfig());
        case LEAST_REQUEST:
          if (enableLeastRequest) {
            return buildWrrLocalityConfig(convertLeastRequestConfig(cluster));
          }
          break;
        default:
      }
      throw new ResourceInvalidException(
          "Cluster " + cluster.getName() + ": unsupported lb policy: " + cluster.getLbPolicy());
    }

    /**
     * Creates a new ring_hash service config JSON object based on the old {@link RingHashLbConfig}
     * config message.
     */
    private static ImmutableMap<String, ?> convertRingHashConfig(Cluster cluster)
        throws ResourceInvalidException {
      RingHashLbConfig lbConfig = cluster.getRingHashLbConfig();

      // The hash function needs to be validated here as it is not exposed in the returned
      // configuration for later validation.
      if (lbConfig.getHashFunction() != RingHashLbConfig.HashFunction.XX_HASH) {
        throw new ResourceInvalidException(
            "Cluster " + cluster.getName() + ": invalid ring hash function: " + lbConfig);
      }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Set the Cluster's lb_policy to ROUND_ROBIN (or RING_HASH/LEAST_REQUEST where supported) for clusters consumed by gRPC clients
  2. Upgrade grpc-xds to a version supporting the policy you need
  3. Route unsupported policies through a non-gRPC proxy tier instead
  4. Check grpc-xds release notes for which lb policies are supported per version

Example fix

# before (Envoy cluster)
lb_policy: MAGLEV
# after
lb_policy: ROUND_ROBIN
Defensive patterns

Strategy: validation

Validate before calling

// Only emit lb policies gRPC supports:
Set<String> supported = Set.of("ROUND_ROBIN", "RING_HASH", "LEAST_REQUEST");
if (!supported.contains(cluster.getLbPolicy().name())) {
  throw new IllegalArgumentException("lb_policy not supported by gRPC: " + cluster.getLbPolicy());
}

Try / catch

try {
  serviceConfig = convertToServiceConfig(cluster, ...);
} catch (ResourceInvalidException e) {
  logger.warning("Cluster rejected: " + e.getMessage());
  // route cluster through proxy tier or use ROUND_ROBIN fallback
}

Prevention

When it happens

Trigger: A CDS Cluster whose lb_policy field is an unsupported value (falls to the default branch of the switch) is converted while building the service config, e.g. when a wrr_locality/ring_hash conversion path ultimately delegates to convertToServiceConfig with an unsupported policy.

Common situations: Control plane assigning MAGLEV or RANDOM to a cluster targeted at gRPC clients; Istio/Envoy configs reused verbatim for gRPC; newer Envoy lb policies not yet mapped by the grpc-xds version in use.

Related errors


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