grpc/grpc-java · error · ResourceInvalidException

Invalid address: Empty address is not allowed.

Error message

Invalid address: Empty address is not allowed.

What it means

A server-side Listener must carry a concrete socket address so gRPC knows which port the filters apply to. If address.socket_address.address is present but empty, the Listener is rejected with 'Invalid address: Empty address is not allowed.'

Solutions

  1. Set an explicit IP literal (e.g. 0.0.0.0 or the pod IP) in address.socket_address.address on the management server
  2. Fix listener-generation logic so every server-side Listener gets a concrete bind address
  3. Check whether named_port was intended — gRPC requires port_value and a non-empty address
  4. Re-push the corrected Listener so the update is ACKed

Example fix

// before
address { socket_address { protocol: TCP port_value: 9090 } }
// after
address { socket_address { protocol: TCP address: "0.0.0.0" port_value: 9090 } }
Defensive patterns

Strategy: validation

Validate before calling

// Control-plane side: require a non-empty address and port_value
if (listener.getAddress().hasSocketAddress()) {
  String addr = listener.getAddress().getSocketAddress().getAddress();
  if (addr.isEmpty()) {
    throw new IllegalArgumentException("Invalid address: Empty address is not allowed.");
  }
}

Type guard

boolean hasConcreteSocketAddress(io.envoyproxy.envoy.config.listener.v3.Listener listener) {
  return listener.getAddress().hasSocketAddress()
      && !listener.getAddress().getSocketAddress().getAddress().isEmpty();
}

Try / catch

// Client side: detect empty listener addresses from watcher errors
@Override public void onError(Status error) {
  if (error.getDescription().contains("Empty address is not allowed")) {
    logger.log(WARNING, "Listener has empty socket address: " + error.getDescription());
  }
}

Prevention

When it happens

Trigger: A Listener proto has address.socket_address set but its address field is an empty string; parseServerSideListener throws before evaluating port specifiers. (Note: named_port is also rejected separately.)

Common situations: Management server generating listener templates without filling the bind address; hand-written LDS resources with address omitted inside socket_address; configs relying on Envoy's default/empty bind behavior that gRPC does not allow.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

      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:
          // noop
      }
    }

    ImmutableList.Builder<FilterChain> filterChains = ImmutableList.builder();
    Set<String> filterChainNames = new HashSet<>();
    Set<FilterChainMatch> filterChainMatchSet = new HashSet<>();
    int i = 0;
    for (io.envoyproxy.envoy.config.listener.v3.FilterChain fc : proto.getFilterChainsList()) {
      // May be empty. If it's not empty, required to be unique.

View on GitHub (pinned to 64daddc1f3)