grpc/grpc-java · error · ResourceInvalidException

structOrError.getErrorDetail()

Error message

structOrError.getErrorDetail()

What it means

After resolving the cluster's type-specific parsing, processCluster re-throws any error detail stored in the resulting StructOrError as a ResourceInvalidException. This propagates an error that occurred inside a nested parser (e.g. parseEdsCluster, parseAggregateCluster) up to the CDS resource parse layer.

Source

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

                                  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());
    }

    updateBuilder.lbPolicyConfig(configOrError.getConfig(), lbPolicyConfig);
    updateBuilder.filterMetadata(
        ImmutableMap.copyOf(cluster.getMetadata().getFilterMetadataMap()));

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Read the propagated errorDetail message to identify which cluster field the nested parser rejected
  2. Fix the corresponding cluster configuration on the management server
  3. Check grpc-java version support for the control plane's features (e.g. newer cluster fields)

Example fix

// before
AggregateCluster.newBuilder().addClusterNames("").build()
// after
AggregateCluster.newBuilder().addClusterNames("child_cluster_1").build()
Defensive patterns

Strategy: try-catch

Try / catch

try {
  cdsUpdate = xdsClusterResource.parseResource(args);
} catch (ResourceInvalidException e) {
  // e.getMessage() carries the nested parser's errorDetail; surface it to config owners
  logger.atWarning().log("CDS parse failed: %s", e.getMessage());
  nackResource(e.getMessage());
}

Prevention

When it happens

Trigger: Any of the per-type parsers (parseNonAggregateCluster, parseAggregateCluster, etc.) return a StructOrError whose errorDetail is non-null, e.g. invalid EDS config, missing load_assignment, bad LRS config.

Common situations: EDS cluster missing eds_cluster_config; aggregate cluster with empty/degenerate localities list; unsupported lb policy features for the cluster type.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/ab6f923c530b8682. Report an issue: GitHub.