{"record":{"id":"e26c28d7c8820e2c","repo":"cilium/cilium","slug":"tx-w","errorCode":null,"errorMessage":"tx: %w","messagePattern":"tx: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/xds/experimental/client/client.go","lineNumber":379,"sourceCode":"}\n\n// handleObserve creates a flavour-specific request based on observeRequest and sends it on given transport trans.\nfunc (c *XDSClient[ReqT, RespT]) handleObserve(trans transport[ReqT, RespT], obsReq *observeRequest) error {\n\treq := c.xds.prepareObsReq(obsReq, c.node, c.getAllResources)\n\tc.log.Debug(\"Send\", logfields.Request, req)\n\n\terr := trans.Send(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"send: %w\", err)\n\t}\n\treturn nil\n}\n\n// handleResponse creates transactions based on flavour-specific responses, applies them to cache.\nfunc (c *XDSClient[ReqT, RespT]) handleResponse(trans transport[ReqT, RespT], resp RespT) error {\n\ttransactions, err := c.xds.tx(resp, c.getAllResources)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"tx: %w\", err)\n\t}\n\tfor _, transaction := range transactions {\n\t\tc.log.Debug(\"cache TX: start\",\n\t\t\tlogfields.XDSTypeURL, transaction.typeUrl,\n\t\t\tlogfields.Upserted, transaction.updated,\n\t\t\tlogfields.Deleted, transaction.deleted,\n\t\t)\n\t\tver, updated, _ := c.cache.TX(transaction.typeUrl, transaction.updated, transaction.deleted)\n\t\tc.log.Debug(\"cache TX: end\",\n\t\t\tlogfields.XDSTypeURL, transaction.typeUrl,\n\t\t\tlogfields.XDSCachedVersion, ver,\n\t\t\tlogfields.Updated, updated,\n\t\t)\n\t}\n\treq := c.xds.ack(c.node, resp, nil)\n\n\tc.log.Debug(\"Send\", logfields.Request, req)\n\terr = trans.Send(req)","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/xds/experimental/client/client.go#L361-L397","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Align proto versions: regenerate/upgrade the client's generated resource types to match the xDS server's version.","Verify the typeUrl of the failing response matches what the client registered via NewClient/AddResourceWatcher.","Log the failing typeUrl and resource name (present in the response) to identify the offending resource.","Check for a proxy mangling responses; compare against a direct server connection.","If the server legitimately sends new fields, upgrade the client library rather than pinning old protos."],"exampleFix":"// before\ncl, _ := xdsclient.NewClient(cfg) // generated protos v1, server emits v3 resources\n// after\n// regenerate resource protos with the same API version the xDS server serves\ncl, err := xdsclient.NewClient(cfg) // protos now match response schema; tx succeeds","handlingStrategy":"validation","validationCode":"// ensure registered type URLs match what the server serves before running\nfor _, u := range cfg.TypeURLs {\n\tif !serverServesType(u) { return fmt.Errorf(\"client type %q not served by xDS server\", u) }\n}","typeGuard":"func isTxParseErr(err error) bool { return strings.HasPrefix(err.Error(), \"tx: parse resource\") }","tryCatchPattern":"err := cl.Run(ctx)\nif err != nil && strings.Contains(err.Error(), \"tx:\") {\n\tlog.Errorf(\"xDS response could not be converted: %v\", errors.Unwrap(err))\n\t// pin server version or upgrade client protos, then restart\n}","preventionTips":["Keep generated resource protos versioned with the xDS server deployment.","Register only typeUrls the server actually serves.","Test client/server compatibility in CI before upgrades.","Reject unexpected typeUrls early with a clear log line."],"tags":["xds","proto","schema","parsing"],"backgroundTag":"schema-validation-failed","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}