{"record":{"id":"3fb33f6dff3b4c04","repo":"grpc/grpc-java","slug":"failed-to-parse-endpoint-metadata-e-getmessage","errorCode":null,"errorMessage":"Failed to parse Endpoint metadata: ${e.getMessage()}","messagePattern":"Failed to parse Endpoint metadata: (.+?)","errorType":"validation","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/XdsEndpointResource.java","lineNumber":224,"sourceCode":"    MetadataRegistry registry = MetadataRegistry.getInstance();\n    try {\n      localityMetadata = registry.parseMetadata(proto.getMetadata());\n    } catch (ResourceInvalidException e) {\n      throw new ResourceInvalidException(\"Failed to parse Locality Endpoint metadata: \"\n          + e.getMessage(), e);\n    }\n    List<Endpoints.LbEndpoint> endpoints = new ArrayList<>(proto.getLbEndpointsCount());\n    for (io.envoyproxy.envoy.config.endpoint.v3.LbEndpoint endpoint : proto.getLbEndpointsList()) {\n      // The endpoint field of each lb_endpoints must be set.\n      // Inside of it: the address field must be set.\n      if (!endpoint.hasEndpoint() || !endpoint.getEndpoint().hasAddress()) {\n        return StructOrError.fromError(\"LbEndpoint with no endpoint/address\");\n      }\n      ImmutableMap<String, Object> endpointMetadata;\n      try {\n        endpointMetadata = registry.parseMetadata(endpoint.getMetadata());\n      } catch (ResourceInvalidException e) {\n        throw new ResourceInvalidException(\"Failed to parse Endpoint metadata: \"\n            + e.getMessage(), e);\n      }\n      List<java.net.SocketAddress> addresses = new ArrayList<>();\n      addresses.add(getInetSocketAddress(endpoint.getEndpoint().getAddress()));\n\n      if (isEnabledXdsDualStack()) {\n        for (Endpoint.AdditionalAddress additionalAddress\n            : endpoint.getEndpoint().getAdditionalAddressesList()) {\n          addresses.add(getInetSocketAddress(additionalAddress.getAddress()));\n        }\n      }\n      boolean isHealthy = (endpoint.getHealthStatus() == HealthStatus.HEALTHY)\n              || (endpoint.getHealthStatus() == HealthStatus.UNKNOWN);\n      endpoints.add(Endpoints.LbEndpoint.create(\n          new EquivalentAddressGroup(addresses),\n          endpoint.getLoadBalancingWeight().getValue(), isHealthy,\n          endpoint.getEndpoint().getHostname(),\n          endpointMetadata));","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/XdsEndpointResource.java#L206-L242","documentation":"When parsing each LbEndpoint of an EDS ClusterLoadAssignment, gRPC parses endpoint-level metadata via MetadataRegistry.parseMetadata. If the endpoint's metadata Struct is invalid, the entire EDS resource is rejected with this ResourceInvalidException and the update is NACKed.","triggerScenarios":"An EDS resource arrives where lb_endpoints[i].metadata contains a Struct that fails MetadataRegistry.parseMetadata (unsupported value type, invalid nested structure, or a field violating the metadata schema). The exception is rethrown with this prefix in parseLocalityLbEndpoints.","commonSituations":"Custom xDS management server attaches endpoint metadata in a non-conforming format; Istio/Envoy emits metadata extensions gRPC does not accept; manually crafted load assignment protos with garbage metadata fields.","solutions":["Read the appended cause message to identify the exact metadata key/value that failed","Correct the per-endpoint metadata Struct in the EDS resource on the management server","Remove unsupported metadata keys or encode values with supported Struct types","Re-send the corrected resource so gRPC ACKs the update"],"exampleFix":"// before\nlb_endpoints { metadata { fields { key: \"weight\" value { string_value: \"ten\" } } } }\n// after\nlb_endpoints { metadata { fields { key: \"weight\" value { number_value: 10 } } } }","handlingStrategy":"validation","validationCode":"// Control-plane side: validate endpoint metadata before sending\nMetadataRegistry registry = MetadataRegistry.getInstance();\nfor (var lbEndpoint : loadAssignment.getEndpoints(0).getLbEndpointsList()) {\n  try {\n    registry.parseMetadata(lbEndpoint.getMetadata());\n  } catch (ResourceInvalidException e) {\n    throw new IllegalStateException(\"Invalid endpoint metadata: \" + e.getMessage(), e);\n  }\n}","typeGuard":"boolean isValidEndpointMetadata(com.google.protobuf.Struct metadata) {\n  try {\n    MetadataRegistry.getInstance().parseMetadata(metadata);\n    return true;\n  } catch (ResourceInvalidException e) {\n    return false;\n  }\n}","tryCatchPattern":"// Client side: capture the NACK reason from the watcher error status\n@Override public void onError(Status error) {\n  if (error.getDescription().contains(\"Failed to parse Endpoint metadata\")) {\n    logger.log(WARNING, \"Bad endpoint metadata in EDS resource: \" + error.getDescription());\n  }\n}","preventionTips":["Validate per-endpoint metadata Structs on the management server before publishing","Restrict endpoint metadata to documented gRPC xDS metadata keys and types","Pin/align control plane and grpc-xds versions so metadata expectations match","Enable FINE logging for io.grpc.xds to see full NACK reasons early"],"tags":["grpc","xds","metadata","eds","control-plane"],"backgroundTag":"schema-validation-failed","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}