grpc/grpc-go · error

unsupported field 'use_original_dst' is present and set to t

Error message

unsupported field 'use_original_dst' is present and set to true

What it means

Returned by processServerSideListener (unmarshal_lds.go:276-277) when the LDS Listener has use_original_dst set to true. gRPC's xDS server-side listener model does not implement original-destination-based routing (an Envoy feature), so the listener resource is rejected to avoid silently misrouting traffic. The check is an explicit guard early in server listener processing.

Source

Thrown at internal/xds/xdsclient/xdsresource/unmarshal_lds.go:277

	}
	var i int
	for ; i < len(ret)-1; i++ {
		if ret[i].Filter.IsTerminal() {
			return nil, fmt.Errorf("http filter %q is a terminal filter but it is not last in the filter chain", ret[i].Name)
		}
	}
	if !ret[i].Filter.IsTerminal() {
		return nil, fmt.Errorf("http filter %q is not a terminal filter", ret[len(ret)-1].Name)
	}
	return ret, nil
}

func processServerSideListener(lis *v3listenerpb.Listener) (*ListenerUpdate, error) {
	if n := len(lis.ListenerFilters); n != 0 {
		return nil, fmt.Errorf("unsupported field 'listener_filters' contains %d entries", n)
	}
	if lis.GetUseOriginalDst().GetValue() {
		return nil, errors.New("unsupported field 'use_original_dst' is present and set to true")
	}
	addr := lis.GetAddress()
	if addr == nil {
		return nil, fmt.Errorf("no address field in LDS response: %+v", lis)
	}
	sockAddr := addr.GetSocketAddress()
	if sockAddr == nil {
		return nil, fmt.Errorf("no socket_address field in LDS response: %+v", lis)
	}
	lu := &ListenerUpdate{
		TCPListener: &InboundListenerConfig{
			Address: sockAddr.GetAddress(),
			Port:    strconv.Itoa(int(sockAddr.GetPortValue())),
		},
	}

	// Populate the default filter chain.
	if dfc := lis.GetDefaultFilterChain(); dfc != nil {

View on GitHub (pinned to 03255a9237)

Solutions

  1. Set use_original_dst to false (or omit it) in the server-side Listener resource for gRPC xDS.
  2. If original-destination routing is required, keep that logic in Envoy/sidecar rather than the gRPC xDS server listener.
  3. Update the control-plane listener template to drop original_dst fields when targeting gRPC.

Example fix

// before
//   listener: { use_original_dst: true, ... }
// after
//   listener: { use_original_dst: false, ... }   // or omit the field
Defensive patterns

Strategy: validation

Validate before calling

func listenerUsesNoOriginalDst(lis *v3listenerpb.Listener) error {
    if lis.GetUseOriginalDst().GetValue() {
        return errors.New("use_original_dst is unsupported by gRPC xDS")
    }
    return nil
}

Prevention

When it happens

Trigger: An xDS server-side Listener resource with use_original_dst=true is received by the gRPC xDS client. processServerSideListener reads lis.GetUseOriginalDst().GetValue() and, on true, returns the error, NACKing the resource.

Common situations: Reusing an Envoy listener config verbatim that relies on original_dst; a control plane template that sets use_original_dst by default; porting a service-mesh listener to gRPC xDS.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/3f46f004e37fe999. Report an issue: GitHub.