prometheus/node_exporter · error

couldn't get routes

Error message

couldn't get routes: %w

What it means

The network_route collector lists routes via conn.Route.List() after fetching links. If the rtnetlink route dump or parse fails, Update returns this wrapped error and the route count metrics are not produced.

Solutions

  1. Retry the scrape; large-table ENOBUFS failures are sometimes transient.
  2. Increase netlink dump buffer capacity by updating mdlayher/netlink/rtnetlink (or adjust socket buffers via syscall).
  3. Trim the routing table size on the host if it's unexpectedly large.
  4. Update node_exporter and its netlink dependencies; report persistent parse errors upstream with `ip route | wc -l` and kernel version.

Example fix

// before
routes, err := conn.Route.List()
if err != nil {
	return fmt.Errorf("couldn't get routes: %w", err)
}
// after (add table-size context for diagnosing buffer overflows)
routes, err := conn.Route.List()
if err != nil {
	return fmt.Errorf("couldn't get routes (large routing table may exceed netlink buffer): %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

null

Try / catch

// Retry once; then report with table-size context
routes, err := conn.Route.List()
if err != nil {
	time.Sleep(50 * time.Millisecond)
	if routes, err = conn.Route.List(); err != nil {
		return fmt.Errorf("couldn't get routes: %w", err)
	}
}

Prevention

When it happens

Trigger: conn.Route.List() fails when the netlink route dump errors out (ENOBUFS buffer overflow with very large routing tables, socket issues, unparseable route attributes from newer kernels).

Common situations: Hosts/routers with huge routing tables (thousands of BGP routes) overflowing default netlink dump buffers; kernel versions emitting attributes the pinned rtnetlink library can't parse.

Related errors


AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07). Data as JSON: /api/errors/9098171fab720b31. Report an issue: GitHub.

Appendix: source

Thrown at collector/network_route_linux.go:75

}

func (n networkRouteCollector) Update(ch chan<- prometheus.Metric) error {
	deviceRoutes := make(map[string]int)

	conn, err := rtnetlink.Dial(nil)
	if err != nil {
		return fmt.Errorf("couldn't connect rtnetlink: %w", err)
	}
	defer conn.Close()

	links, err := conn.Link.List()
	if err != nil {
		return fmt.Errorf("couldn't get links: %w", err)
	}

	routes, err := conn.Route.List()
	if err != nil {
		return fmt.Errorf("couldn't get routes: %w", err)
	}

	for _, route := range routes {
		if route.Type != unix.RTA_DST {
			continue
		}
		if len(route.Attributes.Multipath) != 0 {
			for _, nextHop := range route.Attributes.Multipath {
				ifName := ""
				for _, link := range links {
					if link.Index == nextHop.Hop.IfIndex {
						ifName = link.Attributes.Name
						break
					}
				}

				labels := []string{
					ifName, // if

View on GitHub (pinned to 17ddd77c59)