grpc/grpc-java · error · ResourceInvalidException

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

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.

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)

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.