grpc/grpc-java · error · ResourceInvalidException

Cluster " + cluster.getName() + ": unspecified cluster disco

Error message

Cluster " + cluster.getName() + ": unspecified cluster discovery type

What it means

When parsing a Cluster proto, processCluster switches on the cluster_type oneof. If the discovery type is CLUSTERDISCOVERYTYPE_NOT_SET (or an unrecognized value), the cluster does not declare how it is discovered (STATIC, STRICT_DNS, EDS, LOGICAL_DNS, or AGGREGATE), so parsing throws ResourceInvalidException.

Source

Thrown at xds/src/main/java/io/grpc/xds/XdsClusterResource.java:156

  @VisibleForTesting
  static CdsUpdate processCluster(Cluster cluster,
                                  Set<String> certProviderInstances,
                                  ServerInfo serverInfo,
                                  LoadBalancerRegistry loadBalancerRegistry)
      throws ResourceInvalidException {
    StructOrError<CdsUpdate.Builder> structOrError;
    switch (cluster.getClusterDiscoveryTypeCase()) {
      case TYPE:
        structOrError = parseNonAggregateCluster(cluster,
            certProviderInstances, serverInfo);
        break;
      case CLUSTER_TYPE:
        structOrError = parseAggregateCluster(cluster);
        break;
      case CLUSTERDISCOVERYTYPE_NOT_SET:
      default:
        throw new ResourceInvalidException(
            "Cluster " + cluster.getName() + ": unspecified cluster discovery type");
    }
    if (structOrError.getErrorDetail() != null) {
      throw new ResourceInvalidException(structOrError.getErrorDetail());
    }
    CdsUpdate.Builder updateBuilder = structOrError.getStruct();

    ImmutableMap<String, ?> lbPolicyConfig = LoadBalancerConfigFactory.newConfig(cluster,
        enableLeastRequest);

    NameResolver.ConfigOrError configOrError
        = GracefulSwitchLoadBalancer.parseLoadBalancingPolicyConfig(
            ImmutableList.of(lbPolicyConfig), loadBalancerRegistry);
    if (configOrError.getError() != null) {
      throw new ResourceInvalidException(
          "Failed to parse lb config for cluster '" + cluster.getName() + "': "
          + configOrError.getError());
    }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Set a valid discovery type on the cluster config at the management server (e.g. EDS with eds_cluster_config, or STATIC with load_assignment)
  2. Update the xDS control plane so emitted clusters always populate the cluster_type oneof
  3. Add validation on the server before publishing CDS resources

Example fix

// before
Cluster.newBuilder().setName("cluster1").build()
// after
Cluster.newBuilder().setName("cluster1")
    .setType(Cluster.DiscoveryType.EDS)
    .setEdsClusterConfig(Cluster.EdsClusterConfig.newBuilder().setEdsServiceName("cluster1"))
    .build()
Defensive patterns

Strategy: validation

Validate before calling

if (cluster.getClusterTypeCase() == Cluster.ClusterTypeCase.CLUSTERDISCOVERYTYPE_NOT_SET) {
  throw new ResourceInvalidException("Cluster " + cluster.getName() + " has no discovery type");
}

Type guard

boolean hasDiscoveryType(Cluster c) {
  return c.getClusterTypeCase() != Cluster.ClusterTypeCase.CLUSTERDISCOVERYTYPE_NOT_SET;
}

Try / catch

try {
  cdsUpdate = xdsClusterResource.parseResource(args);
} catch (ResourceInvalidException e) {
  logger.atWarning().log("Cluster rejected: %s", e.getMessage());
  return Status.INVALID_ARGUMENT.withDescription(e.getMessage()).asException();
}

Prevention

When it happens

Trigger: The xDS server sends a Cluster message with neither server_discovery_type, cluster_type, nor the EDS fields populated, i.e. the oneof is unset.

Common situations: Control-plane bugs emitting empty cluster protos; hand-crafted test fixtures missing cluster_type; proto serialization dropping default-valued fields when the server builds the Cluster incorrectly.

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