grpc/grpc-java · error · ResourceInvalidException

Invalid LoadBalancingPolicy: " + loadBalancingPolicy

Error message

Invalid LoadBalancingPolicy: " + loadBalancingPolicy

What it means

ResourceInvalidException thrown by LoadBalancerConfigFactory.convertToServiceConfig when the cluster's lb_policy/typed extension config could be converted, but no LoadBalancer Provider with the resulting policy name exists in the LoadBalancerRegistry. The xDS control plane requested a load-balancing policy this client neither recognizes nor has on its classpath.

Source

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

        } catch (InvalidProtocolBufferException e) {
          throw new ResourceInvalidException(
              "Unable to unpack typedConfig for: " + typedConfig.getTypeUrl(), e);
        }
        // The service config is expected to have a single root entry, where the name of that entry
        // is the name of the policy. A Load balancer with this name must exist in the registry.
        if (serviceConfig == null || LoadBalancerRegistry.getDefaultRegistry()
            .getProvider(Iterables.getOnlyElement(serviceConfig.keySet())) == null) {
          logger.log(XdsLogLevel.WARNING, "Policy {0} not found in the LB registry, skipping",
              typedConfig.getTypeUrl());
          continue;
        } else {
          return serviceConfig;
        }
      }

      // If we could not find a Policy that we could both convert as well as find a provider for
      // then we have an invalid LB policy configuration.
      throw new ResourceInvalidException("Invalid LoadBalancingPolicy: " + loadBalancingPolicy);
    }

    /**
     * Converts a ring_hash {@link Any} configuration to service config format.
     */
    private static ImmutableMap<String, ?> convertRingHashConfig(RingHash ringHash)
        throws ResourceInvalidException {
      // The hash function needs to be validated here as it is not exposed in the returned
      // configuration for later validation.
      if (RingHash.HashFunction.XX_HASH != ringHash.getHashFunction()) {
        throw new ResourceInvalidException(
            "Invalid ring hash function: " + ringHash.getHashFunction());
      }

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

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Ensure the required grpc-java LB provider artifact is on the classpath (e.g. io.grpc:grpc-services includes providers) so the policy name resolves in LoadBalancerRegistry
  2. Fix the control-plane config to use a policy supported by grpc-java (round_robin, weighted_round_robin, ring_hash, least_request, wrr_locality)
  3. Upgrade grpc-xds to a version that supports the requested LB policy
  4. Enable xDS client logging to see which policy name failed

Example fix

// before: control plane sends custom policy
{
  "lb_policy": { "name": "my-custom-lb", "typed_config": {...} }
}
// after: use a supported policy
{
  "lb_policy": { "name": "round_robin", "typed_config": { "@type": "type.googleapis.com/envoy.extensions.transport_sockets...RoundRobin" } }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the provider exists before requesting the policy from the control plane
String policyName = /* policy name from cluster lb config */;
if (LoadBalancerRegistry.getDefaultRegistry().getProvider(policyName) == null) {
  throw new IllegalStateException("LB policy not registered: " + policyName);
}

Try / catch

try {
  /* create channel / start xDS client */;
} catch (ResourceInvalidException e) {
  if (e.getMessage().startsWith("Invalid LoadBalancingPolicy:")) {
    // fall back to a default resolver/service config
    logger.warning(e.getMessage());
  } else { throw e; }
}

Prevention

When it happens

Trigger: convertToServiceConfig (called from convertWrrLocalityConfig) receives a cluster whose LB policy name, after conversion, is not registered via LoadBalancerRegistry.getProvider(), e.g. an unknown custom policy name or a policy provider not on the classpath.

Common situations: Control plane sends a custom LB policy (custom LB extension) that grpc-java doesn't ship; grpc-xds artifact missing the provider dependency (e.g. missing grpc-rls or weighted-round-robin registration); policy name typo in Envoy config.

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/dd4077368d4d9fdb. Report an issue: GitHub.