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
- 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
- Fix the control-plane config to use a policy supported by grpc-java (round_robin, weighted_round_robin, ring_hash, least_request, wrr_locality)
- Upgrade grpc-xds to a version that supports the requested LB policy
- 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
- Verify all required LB provider classes are on the runtime classpath
- Only configure policies the grpc-java version supports
- Log the full cluster resource when an unknown policy is rejected
- Keep grpc-xds upgraded for newer policy support
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
- Maximum LB config recursion depth reached
- Cluster " + cluster.getName() + ": unsupported lb policy: "
- Invalid bootstrap: 'xds_servers' is empty
- Invalid bootstrap: server ${serverUri} 'channel_creds' requi
- Server ${serverUri}: no supported channel credentials found
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/dd4077368d4d9fdb.
Report an issue: GitHub.