cilium/cilium · error

tx: %w

Error message

tx: %w

What it means

handleResponse wraps a failure from the flavour-specific c.xds.tx() — converting a DiscoveryResponse into cache transactions — as 'tx: %w'. For the delta flavour this is typically parseResource failing on a resource Any payload. The error propagates to loop and, if non-retriable, terminates the client.

Source

Thrown at pkg/xds/experimental/client/client.go:379

}

// handleObserve creates a flavour-specific request based on observeRequest and sends it on given transport trans.
func (c *XDSClient[ReqT, RespT]) handleObserve(trans transport[ReqT, RespT], obsReq *observeRequest) error {
	req := c.xds.prepareObsReq(obsReq, c.node, c.getAllResources)
	c.log.Debug("Send", logfields.Request, req)

	err := trans.Send(req)
	if err != nil {
		return fmt.Errorf("send: %w", err)
	}
	return nil
}

// handleResponse creates transactions based on flavour-specific responses, applies them to cache.
func (c *XDSClient[ReqT, RespT]) handleResponse(trans transport[ReqT, RespT], resp RespT) error {
	transactions, err := c.xds.tx(resp, c.getAllResources)
	if err != nil {
		return fmt.Errorf("tx: %w", err)
	}
	for _, transaction := range transactions {
		c.log.Debug("cache TX: start",
			logfields.XDSTypeURL, transaction.typeUrl,
			logfields.Upserted, transaction.updated,
			logfields.Deleted, transaction.deleted,
		)
		ver, updated, _ := c.cache.TX(transaction.typeUrl, transaction.updated, transaction.deleted)
		c.log.Debug("cache TX: end",
			logfields.XDSTypeURL, transaction.typeUrl,
			logfields.XDSCachedVersion, ver,
			logfields.Updated, updated,
		)
	}
	req := c.xds.ack(c.node, resp, nil)

	c.log.Debug("Send", logfields.Request, req)
	err = trans.Send(req)

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Align proto versions: regenerate/upgrade the client's generated resource types to match the xDS server's version.
  2. Verify the typeUrl of the failing response matches what the client registered via NewClient/AddResourceWatcher.
  3. Log the failing typeUrl and resource name (present in the response) to identify the offending resource.
  4. Check for a proxy mangling responses; compare against a direct server connection.
  5. If the server legitimately sends new fields, upgrade the client library rather than pinning old protos.

Example fix

// before
cl, _ := xdsclient.NewClient(cfg) // generated protos v1, server emits v3 resources
// after
// regenerate resource protos with the same API version the xDS server serves
cl, err := xdsclient.NewClient(cfg) // protos now match response schema; tx succeeds
Defensive patterns

Strategy: validation

Validate before calling

// ensure registered type URLs match what the server serves before running
for _, u := range cfg.TypeURLs {
	if !serverServesType(u) { return fmt.Errorf("client type %q not served by xDS server", u) }
}

Type guard

func isTxParseErr(err error) bool { return strings.HasPrefix(err.Error(), "tx: parse resource") }

Try / catch

err := cl.Run(ctx)
if err != nil && strings.Contains(err.Error(), "tx:") {
	log.Errorf("xDS response could not be converted: %v", errors.Unwrap(err))
	// pin server version or upgrade client protos, then restart
}

Prevention

When it happens

Trigger: The xDS server sends a DeltaDiscoveryResponse whose resource Any payload does not unmarshal into the expected protobuf type (parseResource fails) or whose typeUrl does not match a registered type, so tx() returns an error.

Common situations: Version skew: server emits a newer proto version than the client's generated types; wrong resource type registered for a typeUrl; corrupted/truncated response from a proxy; server misconfiguration sending a resource type the client never subscribed to.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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