grpc/grpc-java · error · ResourceInvalidException

Cluster " + cluster.getName() + ": invalid ring hash…

Error message

Cluster " + cluster.getName() + ": invalid ring hash function: " + lbConfig

What it means

The legacy RingHashLbConfig on a Cluster must use the XX_HASH hash function. convertRingHashConfig validates this before building the ring_hash service config because the hash function is not represented in the returned JSON config, so an invalid value would otherwise be silently ignored.

Solutions

  1. Change the ring hash lb config's hash_function to XX_HASH on the management server
  2. If hash_function is omitted, ensure the control plane's default is XX_HASH or set it explicitly
  3. Inspect the CDS payload (xDS debug logging) to confirm what is being sent
  4. Upgrade control plane images that predate xx_hash defaulting

Example fix

// before
RingHashLbConfig.newBuilder().setHashFunction(HashFunction.MURMUR_HASH_2)
// after
RingHashLbConfig.newBuilder().setHashFunction(HashFunction.XX_HASH)
Defensive patterns

Strategy: validation

Validate before calling

if (lbConfig.getHashFunction() != RingHashLbConfig.HashFunction.XX_HASH) {
  throw new IllegalArgumentException("ring hash must use XX_HASH, got " + lbConfig.getHashFunction());
}

Try / catch

try {
  serviceConfig = convertRingHashConfig(cluster);
} catch (ResourceInvalidException e) {
  logger.warning("ring_hash config rejected: " + e.getMessage());
  // fail resource or substitute a compliant ring_hash config
}

Prevention

When it happens

Trigger: convertToServiceConfig dispatches a Cluster with lb_policy RING_HASH to convertRingHashConfig; the Cluster's RingHashLbConfig.hash_function is anything other than XX_HASH.

Common situations: Older Envoy/Istio configs defaulting to murmur2; control plane templates not migrated after xx_hash became required; hand-rolled xDS test servers emitting deprecated hash functions.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

          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);
      }

      return buildRingHashConfig(
          lbConfig.hasMinimumRingSize() ? (Long) lbConfig.getMinimumRingSize().getValue() : null,
          lbConfig.hasMaximumRingSize() ? (Long) lbConfig.getMaximumRingSize().getValue() : null);
    }

    /**
     * Creates a new least_request service config JSON object based on the old {@link
     * LeastRequestLbConfig} config message.
     */
    private static ImmutableMap<String, ?> convertLeastRequestConfig(Cluster cluster) {
      LeastRequestLbConfig lbConfig = cluster.getLeastRequestLbConfig();
      return buildLeastRequestConfig(
          lbConfig.hasChoiceCount() ? (Integer) lbConfig.getChoiceCount().getValue() : null);
    }
  }

View on GitHub (pinned to 64daddc1f3)