cilium/cilium · error

failed to fetch unreachable routes: %w

Error message

failed to fetch unreachable routes: %w

What it means

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.

Source

Thrown at pkg/ipam/pool.go:392

// cleanupUnreachableRoutes removes all unreachable routes for the given prefix.
// This is only needed if EnableUnreachableRoutes has been set.
func cleanupUnreachableRoutes(prefix netip.Prefix) error {
	var family int
	switch prefixFamily(prefix) {
	case IPv4:
		family = netlink.FAMILY_V4
	case IPv6:
		family = netlink.FAMILY_V6
	default:
		return errors.New("unknown cidr family")
	}

	routes, err := safenetlink.RouteListFiltered(family, &netlink.Route{
		Table: unix.RT_TABLE_MAIN,
		Type:  unix.RTN_UNREACHABLE,
	}, netlink.RT_FILTER_TABLE|netlink.RT_FILTER_TYPE)
	if err != nil {
		return fmt.Errorf("failed to fetch unreachable routes: %w", err)
	}

	var errs error
	for _, route := range routes {
		if route.Dst == nil {
			continue
		}
		routePrefix, ok := netipx.FromStdIPNet(route.Dst)
		if !ok {
			continue
		}
		if !containsPrefix(prefix, routePrefix) {
			continue
		}

		err = netlink.RouteDel(&route)
		if err != nil && !errors.Is(err, unix.ESRCH) {
			// We ignore ESRCH, as it means the entry was already deleted

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Grant the agent CAP_NET_ADMIN and run with host networking (hostNetwork: true, privileged where needed)
  2. Check for netlink ENOBUFS under load; reduce route churn or raise socket buffers
  3. Verify kernel/netlink support for filtered route dumps; upgrade kernel or Cilium if unsupported
  4. If transient, retry cleanup on the next updatePool pass
Defensive patterns

Strategy: retry

Validate before calling

// precheck privileges and mount before running route cleanup
if !hasCapNetAdmin() { return errors.New("CAP_NET_ADMIN required for netlink route ops") }
if _, err := os.Stat("/sys/class/net"); err != nil { return errors.New("host network namespace required") }

Try / catch

if err := pool.cleanupUnreachableRoutes(family); err != nil {
    if errors.Is(err, unix.EPERM) || errors.Is(err, unix.ENOBUFS) {
        // transient/permission issue: schedule retry
        time.AfterFunc(time.Minute, func() { _ = pool.cleanupUnreachableRoutes(family) })
    }
    log.Warn("unreachable route cleanup failed", "err", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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