{"record":{"id":"ba266deb70f08be3","repo":"grpc/grpc-java","slug":"missing-ringhash-configuration","errorCode":null,"errorMessage":"Missing RingHash configuration","messagePattern":"Missing RingHash configuration","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/RingHashLoadBalancer.java","lineNumber":106,"sourceCode":"    syncContext = checkNotNull(helper.getSynchronizationContext(), \"syncContext\");\n    logger = XdsLogger.withLogId(InternalLogId.allocate(\"ring_hash_lb\", helper.getAuthority()));\n    logger.log(XdsLogLevel.INFO, \"Created\");\n    this.random = checkNotNull(random, \"random\");\n  }\n\n  @Override\n  public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {\n    logger.log(XdsLogLevel.DEBUG, \"Received resolution result: {0}\", resolvedAddresses);\n    List<EquivalentAddressGroup> addrList = resolvedAddresses.getAddresses();\n    Status addressValidityStatus = validateAddrList(addrList);\n    if (!addressValidityStatus.isOk()) {\n      return addressValidityStatus;\n    }\n\n    // Now do the ringhash specific logic with weights and building the ring\n    RingHashConfig config = (RingHashConfig) resolvedAddresses.getLoadBalancingPolicyConfig();\n    if (config == null) {\n      throw new IllegalArgumentException(\"Missing RingHash configuration\");\n    }\n    requestHashHeaderKey =\n        config.requestHashHeader.isEmpty()\n            ? null\n            : Metadata.Key.of(config.requestHashHeader, Metadata.ASCII_STRING_MARSHALLER);\n    Map<EquivalentAddressGroup, Long> serverWeights = new HashMap<>();\n    long totalWeight = 0L;\n    for (EquivalentAddressGroup eag : addrList) {\n      Long weight = eag.getAttributes().get(XdsAttributes.ATTR_SERVER_WEIGHT);\n      // Support two ways of server weighing: either multiple instances of the same address\n      // or each address contains a per-address weight attribute. If a weight is not provided,\n      // each occurrence of the address will be counted a weight value of one.\n      if (weight == null) {\n        weight = 1L;\n      }\n      totalWeight += weight;\n      EquivalentAddressGroup addrKey = stripAttrs(eag);\n      if (serverWeights.containsKey(addrKey)) {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/RingHashLoadBalancer.java#L88-L124","documentation":"RingHashLoadBalancer.acceptResolvedAddresses casts the load-balancing policy config to RingHashConfig and throws IllegalArgumentException if it is null. The ring hash LB policy cannot build its consistent-hash ring without its configuration (hash function, ring size bounds, request hash header), so a missing config is a hard error.","triggerScenarios":"The control plane sends a cluster whose lbPolicy is ring_hash but the parsed lb policy config is absent, or an API user calls Helper.createSubchannel/switch to ring_hash without supplying a RingHashConfig via LoadBalancer.Registry.","commonSituations":"Envoy/xDS cluster configs where the ring_hash policy omits required config fields; custom balancer wiring that selects ring_hash without setting the policy config; version mismatches where the config parser silently yields null.","solutions":["Ensure the xDS cluster's ring_hash lb policy carries a valid configuration in the management server config","Check that the grpc-xds version supports the ring_hash fields sent by the control plane and upgrade if needed","When using ring_hash directly, always pass a RingHashConfig (even a default new RingHashConfig()) as the LB policy config"],"exampleFix":"// before\nnameResolver.ResolutionResult result = resultBuilder.setLoadBalancingPolicyConfig(null).build();\n// after\nnameResolver.ResolutionResult result = resultBuilder\n    .setLoadBalancingPolicyConfig(new RingHashLoadBalancer.RingHashConfig()).build();","handlingStrategy":"try-catch","validationCode":"if (lbConfig instanceof RingHashLoadBalancer.RingHashConfig) { /* proceed */ } else { /* supply default config */ }","typeGuard":"boolean hasRingHashConfig(Object cfg) {\n  return cfg instanceof RingHashLoadBalancer.RingHashConfig;\n}","tryCatchPattern":"try {\n  helper.createSubchannel(...);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Missing RingHash configuration\")) {\n    // re-select LB with an explicit RingHashConfig\n  }\n}","preventionTips":["Always provide a RingHashConfig when selecting the ring_hash policy","Verify control-plane cluster configs include ring_hash settings","Pin compatible grpc-java and xDS control-plane versions"],"tags":["grpc","xds","load-balancing","ring-hash"],"backgroundTag":"missing-required-config","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}