cilium/cilium · error

parse resource: %w

Error message

parse resource: %w

What it means

The xDS state-of-the-world client fails to parse one resource in a DiscoveryResponse while processing it in tx(). This is a wrapper around a lower-level parseResource failure (typeUrl mismatch, unmarshal error, unhandled type, or missing name); the original cause is attached via %w. The whole batch of upserted resources is discarded when any single resource fails to parse.

Source

Thrown at pkg/xds/experimental/client/client_sotw.go:56

	for i := range curr.VersionedResources {
		reqResourceNames.Insert(curr.VersionedResources[i].Name)
	}
	reqResourceNames.Insert(obsReq.resourceNames...)

	return &discoverypb.DiscoveryRequest{
		Node:          node,
		TypeUrl:       obsReq.typeUrl,
		ResourceNames: slices.Collect(maps.Keys(reqResourceNames)),
	}
}

func (sotw *sotw) tx(resp *discoverypb.DiscoveryResponse, get getter) (txs, error) {
	typeUrl := resp.GetTypeUrl()
	upsertedResources := make(nameToResource)
	for _, res := range resp.GetResources() {
		msg, name, err := parseResource(typeUrl, res)
		if err != nil {
			return nil, fmt.Errorf("parse resource: %w", err)
		}
		upsertedResources[name] = msg
	}

	var deletedResources []string
	if typeUrl == envoy.ListenerTypeURL || typeUrl == envoy.ClusterTypeURL {
		deletedResources = findMissing(typeUrl, upsertedResources, get)
	}
	transactions := txs{{typeUrl: typeUrl, updated: upsertedResources, deleted: deletedResources}}

	if typeUrl == envoy.ClusterTypeURL {
		deletedResources := findMissing(envoy.EndpointTypeURL, upsertedResources, get)
		transactions = append(transactions, tx{typeUrl: envoy.EndpointTypeURL, deleted: deletedResources})
	}
	return transactions, nil
}

func findMissing(typeUrl string, curr nameToResource, get getter) []string {

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Inspect the wrapped cause (%w) in the error chain to identify which of the four parseResource failures occurred
  2. Verify the DiscoveryResponse type_url matches every resource's Any.type_url sent by the management server
  3. Log and inspect the offending resource (name/type_url) on the server side and fix or remove it
  4. If a custom resource type is being sent, add a case for it in parseResource's type switch

Example fix

// before: server sends resources without setting type_url on each Any
resp := &discoverypb.DiscoveryResponse{TypeUrl: envoy.ClusterTypeURL, Resources: []*anypb.Any{{Value: clusterBytes}}}
// after: set TypeUrl on every Any so it matches the response TypeUrl
resp := &discoverypb.DiscoveryResponse{TypeUrl: envoy.ClusterTypeURL, Resources: []*anypb.Any{{TypeUrl: envoy.ClusterTypeURL, Value: clusterBytes}}}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate each Any before handing the response to the client
for _, res := range resp.GetResources() {
	if res.GetTypeUrl() != resp.GetTypeUrl() {
		return fmt.Errorf("skip response: resource typeUrl %s != %s", res.GetTypeUrl(), resp.GetTypeUrl())
	}
	if _, err := res.UnmarshalNew(); err != nil {
		return fmt.Errorf("skip response: unmarshal: %w", err)
	}
}

Type guard

func isSupportedResource(msg proto.Message) bool {
	switch msg.(type) {
	case *listenerpb.Listener, *clusterpb.Cluster, *endpointpb.ClusterLoadAssignment, *routepb.RouteConfiguration:
		return true
	}
	return false
}

Try / catch

txs, err := sotw.tx(resp, get)
if err != nil {
	var perr *parseError
	if errors.As(err, &perr) {
		log.Warnf("dropping malformed xDS response: %v", err)
		return nil, nil // skip batch, wait for server retry
	}
	return nil, err
}

Prevention

When it happens

Trigger: The xDS management server sends a DiscoveryResponse containing an Any resource whose type_url does not match the response's type_url, whose payload cannot be unmarshaled into the expected proto message, whose type is not Listener/Cluster/ClusterLoadAssignment/RouteConfiguration, or whose extracted name is empty.

Common situations: A misbehaving or buggy control plane (custom istiod, third-party xDS server) sends mixed or malformed resources; envoy-proxy protocol version drift means an unexpected resource type arrives; a resource in the registry has an empty name (e.g. a Cluster created without a name).

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/640cf38e2334bac7. Report an issue: GitHub.