grpc/grpc-java · error · ResourceInvalidException

Listener ${proto.getName()} cannot have use_original_dst set

Error message

Listener ${proto.getName()} cannot have use_original_dst set to true

What it means

gRPC server-side Listener parsing rejects Listener resources with use_original_dst set to true, since original-destination redirection is an Envoy-side feature gRPC does not implement. The Listener is rejected with this error.

Source

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

  }

  @VisibleForTesting
  static EnvoyServerProtoData.Listener parseServerSideListener(
      Listener proto, TlsContextManager tlsContextManager,
      FilterRegistry filterRegistry, Set<String> certProviderInstances, XdsResourceType.Args args)
      throws ResourceInvalidException {
    TrafficDirection trafficDirection = proto.getTrafficDirection();
    if (!trafficDirection.equals(TrafficDirection.INBOUND)
        && !trafficDirection.equals(TrafficDirection.UNSPECIFIED)) {
      throw new ResourceInvalidException(
          "Listener " + proto.getName() + " with invalid traffic direction: " + trafficDirection);
    }
    if (!proto.getListenerFiltersList().isEmpty()) {
      throw new ResourceInvalidException(
          "Listener " + proto.getName() + " cannot have listener_filters");
    }
    if (proto.hasUseOriginalDst()) {
      throw new ResourceInvalidException(
          "Listener " + proto.getName() + " cannot have use_original_dst set to true");
    }

    String address = null;
    SocketAddress socketAddress = null;
    if (proto.getAddress().hasSocketAddress()) {
      socketAddress = proto.getAddress().getSocketAddress();
      address = socketAddress.getAddress();
      if (address.isEmpty()) {
        throw new ResourceInvalidException("Invalid address: Empty address is not allowed.");
      }
      switch (socketAddress.getPortSpecifierCase()) {
        case NAMED_PORT:
          throw new ResourceInvalidException("NAMED_PORT is not supported in gRPC.");
        case PORT_VALUE:
          address = address + ":" + socketAddress.getPortValue();
          break;
        default:

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Remove or set use_original_dst: false on Listeners delivered to gRPC servers
  2. Configure the control plane to emit plain socket-address listeners for gRPC workloads
  3. If transparent proxying is required, terminate original-dst handling in an Envoy proxy in front of the gRPC server instead
  4. Re-push the corrected Listener so gRPC ACKs the update

Example fix

// before
listener { name: "inbound-9090" use_original_dst { value: true } ... }
// after
listener { name: "inbound-9090" ... }
Defensive patterns

Strategy: validation

Validate before calling

// Control-plane side: reject use_original_dst before publishing to gRPC servers
if (listener.hasUseOriginalDst()) {
  throw new IllegalArgumentException("Listener " + listener.getName()
      + " cannot have use_original_dst set to true");
}

Try / catch

// Client side: surface unsupported use_original_dst from watcher errors
@Override public void onError(Status error) {
  if (error.getDescription().contains("use_original_dst")) {
    logger.log(WARNING, "Listener uses unsupported use_original_dst: " + error.getDescription());
  }
}

Prevention

When it happens

Trigger: An LDS Listener for a gRPC server has use_original_dst: true (often present in configs generated for transparent-proxy / iptables interception setups); parseServerSideListener throws.

Common situations: Mesh setups using transparent proxying (iptables REDIRECT with original_dst) whose control plane emits use_original_dst on server listeners; copy-pasted Envoy transparent-proxy configs; Istio-style sidecar configs applied to gRPC servers.

Related errors


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