grpc/grpc-go · error

[xDS node id: %s]: %w

Error message

[xDS node id: %s]: %w

What it means

This is an error annotation wrapper produced by the xDS resolver's config selector (annotateErrorWithNodeID, serviceconfig.go:173). It wraps RPC routing failures with the xDS node ID so you can correlate the failure with the specific xDS-managed channel. It is returned (not panicked) when an RPC cannot be matched to a route or the selected cluster cannot be resolved against the current xDS configuration. The wrapped error is normally a codes.Unavailable status.

Source

Thrown at internal/xds/resolver/serviceconfig.go:174

	sendNewServiceConfig func() // Function to send a new service config to gRPC.

	// Configuration received from the xDS management server.
	virtualHost      virtualHost
	routes           []route
	clusters         map[string]*clusterInfo
	plugins          map[string]*clusterInfo
	httpFilterConfig []xdsresource.HTTPFilter
	xdsConfig        *xdsresource.XDSConfig
}

var errNoMatchedRouteFound = status.Errorf(codes.Unavailable, "no matched route was found")
var errUnsupportedClientRouteAction = status.Errorf(codes.Unavailable, "matched route does not have a supported route action type")

// annotateErrorWithNodeID annotates the given error with the provided xDS node
// ID. This is used by the real config selector when it runs into errors, and
// also by the erroring config selector.
func annotateErrorWithNodeID(err error, nodeID string) error {
	return fmt.Errorf("[xDS node id: %s]: %w", nodeID, err)
}

func (cs *configSelector) SelectConfig(rpcInfo iresolver.RPCInfo) (*iresolver.RPCConfig, error) {
	var rt *route
	md, _ := metadata.FromOutgoingContext(rpcInfo.Context)
	if extraMD, ok := grpcutil.ExtraMetadata(rpcInfo.Context); ok {
		md = metadata.Join(md, extraMD)
		// Remove all binary headers. They are hard to match with. May need
		// to add back if asked by users.
		for k := range md {
			if strings.HasSuffix(k, "-bin") {
				delete(md, k)
			}
		}
	}
	// Loop through routes in order and select first match.
	for _, r := range cs.routes {
		if r.m.Match(rpcInfo.Method, md) {

View on GitHub (pinned to 03255a9237)

Solutions

  1. Inspect the full wrapped error to see the underlying cause (no matched route / unsupported action / cluster error) and note the xDS node ID.
  2. Confirm the called method path (/package.Service/Method) is covered by a route match rule (or a catch-all prefix) in the xDS route configuration.
  3. Dump the received xDS config (enable CSDS / xDS resource logging) and verify virtualHost routes and clusters are present for that node ID.
  4. Verify the xDS node ID in your bootstrap JSON matches the identity the control plane is configuring; fix and restart the client if mismatched.
  5. If transient, the channel will retry on the next xDS config update; use a connectivity-state or ready-check before issuing the RPC.

Example fix

// before: RPC fails because no route matches the method path
resp, err := conn.Invoke(ctx, "/myapp.Billing/Charge", req, out)
// err = rpc error: code = Unavailable desc = [xDS node id: node-1]: no matched route was found

// after: ensure the control-plane route config includes the method path,
// or use a catch-all prefix route, then retry the RPC.
// Route match in xDS: { prefix: "/myapp.Billing/" -> cluster: billing-cluster }
Defensive patterns

Strategy: try-catch

Validate before calling

// Before invoking, check channel readiness on an xDS channel
if conn.GetState() != connectivity.Ready {
    // wait for ready or surface a clearer error before the RPC
}
// Optionally inspect the latest service config via CSDS/admin to confirm
// the method path is routed before issuing the RPC.

Try / catch

// Inspect the returned status from the RPC
resp, err := conn.Invoke(ctx, "/pkg.Svc/Method", req, out)
if err != nil {
    st, _ := status.FromError(err)
    if st.Code() == codes.Unavailable && strings.Contains(st.Message(), "[xDS node id:") {
        // xDS routing/config problem: log node id + underlying msg,
        // surface as config error, optionally retry after xDS refresh
    }
    return err
}

Prevention

When it happens

Trigger: An RPC is invoked on an xDS-configured gRPC channel and configSelector.SelectConfig (serviceconfig.go:177) fails: (1) the method/path matches no route in the LDS/RDS config -> errNoMatchedRouteFound; (2) the matched route's action is not RouteActionRoute -> errUnsupportedClientRouteAction; (3) the resolved cluster object is not a *routeCluster. Additionally, when the channel is in a broken xDS state, newErroringConfigSelector wraps EVERY outgoing RPC with this annotation.

Common situations: The xDS control plane (Traffic Director, Istio, Envoy xDS server) has not delivered a Listener/Route config covering the service/method being called. A new gRPC method path was added in code but not added to the route match rules. The node ID in the bootstrap config does not match what the control plane expects, so no config is ever sent. A transient xDS update left zero valid routes.

Related errors


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