{"record":{"id":"b471136aad55458b","repo":"cilium/cilium","slug":"failed-to-fetch-unreachable-routes-w","errorCode":null,"errorMessage":"failed to fetch unreachable routes: %w","messagePattern":"failed to fetch unreachable routes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ipam/pool.go","lineNumber":392,"sourceCode":"// cleanupUnreachableRoutes removes all unreachable routes for the given prefix.\n// This is only needed if EnableUnreachableRoutes has been set.\nfunc cleanupUnreachableRoutes(prefix netip.Prefix) error {\n\tvar family int\n\tswitch prefixFamily(prefix) {\n\tcase IPv4:\n\t\tfamily = netlink.FAMILY_V4\n\tcase IPv6:\n\t\tfamily = netlink.FAMILY_V6\n\tdefault:\n\t\treturn errors.New(\"unknown cidr family\")\n\t}\n\n\troutes, err := safenetlink.RouteListFiltered(family, &netlink.Route{\n\t\tTable: unix.RT_TABLE_MAIN,\n\t\tType:  unix.RTN_UNREACHABLE,\n\t}, netlink.RT_FILTER_TABLE|netlink.RT_FILTER_TYPE)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to fetch unreachable routes: %w\", err)\n\t}\n\n\tvar errs error\n\tfor _, route := range routes {\n\t\tif route.Dst == nil {\n\t\t\tcontinue\n\t\t}\n\t\troutePrefix, ok := netipx.FromStdIPNet(route.Dst)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif !containsPrefix(prefix, routePrefix) {\n\t\t\tcontinue\n\t\t}\n\n\t\terr = netlink.RouteDel(&route)\n\t\tif err != nil && !errors.Is(err, unix.ESRCH) {\n\t\t\t// We ignore ESRCH, as it means the entry was already deleted","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/ipam/pool.go#L374-L410","documentation":"cleanupUnreachableRoutes lists kernel routing-table entries of type RTN_UNREACHABLE in the main table (routes Cilium installs for pool-excluded prefixes) via a netlink RouteListFiltered call. If the netlink socket query itself fails, the wrapped error is returned so the caller knows stale unreachable routes could not even be enumerated.","triggerScenarios":"updatePool triggers route cleanup and netlink.RouteListFiltered fails: netlink socket exhaustion (ENOBUFS), permission denied (missing CAP_NET_ADMIN), or netlink message truncation with many routes.","commonSituations":"Container missing CAP_NET_ADMIN; host under netlink buffer pressure with huge routing tables; older kernels/OCI runtimes rejecting RT_FILTER_TYPE; running agent in an unprivileged namespace without host network access.","solutions":["Grant the agent CAP_NET_ADMIN and run with host networking (hostNetwork: true, privileged where needed)","Check for netlink ENOBUFS under load; reduce route churn or raise socket buffers","Verify kernel/netlink support for filtered route dumps; upgrade kernel or Cilium if unsupported","If transient, retry cleanup on the next updatePool pass"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// precheck privileges and mount before running route cleanup\nif !hasCapNetAdmin() { return errors.New(\"CAP_NET_ADMIN required for netlink route ops\") }\nif _, err := os.Stat(\"/sys/class/net\"); err != nil { return errors.New(\"host network namespace required\") }","typeGuard":null,"tryCatchPattern":"if err := pool.cleanupUnreachableRoutes(family); err != nil {\n    if errors.Is(err, unix.EPERM) || errors.Is(err, unix.ENOBUFS) {\n        // transient/permission issue: schedule retry\n        time.AfterFunc(time.Minute, func() { _ = pool.cleanupUnreachableRoutes(family) })\n    }\n    log.Warn(\"unreachable route cleanup failed\", \"err\", err)\n}","preventionTips":["Run the agent with CAP_NET_ADMIN and host networking","Monitor netlink errors (ENOBUFS) under large routing tables","Keep kernel versions within Cilium's supported range","Avoid competing route managers modifying table main"],"tags":["network","netlink","routes"],"backgroundTag":"netlink-route-list-failed","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}