grpc/grpc-java · error · ResourceInvalidException

Invalid message type: ${unpackedMessage.getClass()}

Error message

Invalid message type: ${unpackedMessage.getClass()}

What it means

XdsEndpointResource.doParse expects the unpacked Any payload of an EDS (EndpointDiscoveryResponse) resource to be a ClusterLoadAssignment protobuf. If the Any contains some other message type, the parser throws ResourceInvalidException naming the unexpected class.

Source

Thrown at xds/src/main/java/io/grpc/xds/XdsEndpointResource.java:106

  @Override
  public boolean shouldRetrieveResourceKeysForArgs() {
    return true;
  }

  @Override
  protected boolean isFullStateOfTheWorld() {
    return false;
  }

  @Override
  protected Class<ClusterLoadAssignment> unpackedClassName() {
    return ClusterLoadAssignment.class;
  }

  @Override
  protected EdsUpdate doParse(Args args, Message unpackedMessage) throws ResourceInvalidException {
    if (!(unpackedMessage instanceof ClusterLoadAssignment)) {
      throw new ResourceInvalidException("Invalid message type: " + unpackedMessage.getClass());
    }
    return processClusterLoadAssignment((ClusterLoadAssignment) unpackedMessage);
  }

  private static boolean isEnabledXdsDualStack() {
    return GrpcUtil.getFlag(GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS, false);
  }

  private static EdsUpdate processClusterLoadAssignment(ClusterLoadAssignment assignment)
      throws ResourceInvalidException {
    Map<Integer, Set<Locality>> priorities = new HashMap<>();
    Map<Locality, LocalityLbEndpoints> localityLbEndpointsMap = new LinkedHashMap<>();
    List<Endpoints.DropOverload> dropOverloads = new ArrayList<>();
    int maxPriority = -1;
    for (io.envoyproxy.envoy.config.endpoint.v3.LocalityLbEndpoints localityLbEndpointsProto
        : assignment.getEndpointsList()) {
      StructOrError<LocalityLbEndpoints> structOrError =
          parseLocalityLbEndpoints(localityLbEndpointsProto);

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Fix the management server to send ClusterLoadAssignment for EDS type URLs
  2. Verify the resource's Any type_url matches io.grpc.xds EDS expectations
  3. Capture the raw xDS response (grpc-xds debug logs) to inspect the actual payload
  4. Update protobuf/xDS version alignment between control plane and grpc-java
Defensive patterns

Strategy: try-catch

Validate before calling

if (!resource.getMessage().is(ClusterLoadAssignment.class)) {
  throw new IllegalArgumentException("EDS resource is not ClusterLoadAssignment");
}

Type guard

static boolean isClusterLoadAssignment(Any any) {
  return any.is(ClusterLoadAssignment.class);
}

Try / catch

try {
  update = XdsEndpointResource.getInstance().parse(args, resource);
} catch (ResourceInvalidException e) {
  logger.warn("Bad EDS payload: {}", e.getMessage());
}

Prevention

When it happens

Trigger: An EDS response resource whose type_url resolves (via the registered type registry/unpack) to a message that is not ClusterLoadAssignment — e.g. a misconfigured control plane sending the wrong resource body under an EDS type URL.

Common situations: Misbehaving or buggy xDS management server; custom control planes emitting wrong payloads; type-URL/registry mismatches after protobuf upgrades.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — 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/c8ebae19a6f303b6. Report an issue: GitHub.