prometheus/node_exporter · error

couldn't connect rtnetlink

Error message

couldn't connect rtnetlink: %w

What it means

The network_route collector's Update dials the rtnetlink netlink socket (rtnetlink.Dial) to enumerate links and routes. If the netlink socket cannot be created or bound, Update returns this wrapped error and the route metrics are not scraped.

Solutions

  1. Verify the kernel supports netlink (it does on all standard Linux) and that the exporter process can create netlink sockets (test with `ss -f netlink` or a small Go probe).
  2. Review seccomp/AppArmor/SELinux profiles for the exporter and allow AF_NETLINK socket creation.
  3. Run the exporter outside restrictive sandboxes or relax the runtime's syscall filter.
  4. If the collector isn't needed, start node_exporter without the network_route collector (--collector.network-route disabled / blacklist flag).

Example fix

// before
conn, err := rtnetlink.Dial(nil)
if err != nil {
	return fmt.Errorf("couldn't connect rtnetlink: %w", err)
}
// after (surface the underlying cause context)
conn, err := rtnetlink.Dial(nil)
if err != nil {
	return fmt.Errorf("couldn't connect rtnetlink (netlink socket blocked? check seccomp/permissions): %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

import "golang.org/x/sys/unix"
// Probe netlink socket capability before enabling the collector:
fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, unix.NETLINK_ROUTE)
if err != nil {
	// rtnetlink unavailable in this sandbox; disable network-route collector
} else {
	unix.Close(fd)
}

Type guard

null

Try / catch

// Fall back gracefully when netlink is blocked
conn, err := rtnetlink.Dial(nil)
if err != nil {
	logger.Warn("rtnetlink unavailable; skipping network_route metrics", "err", err)
	return nil
}

Prevention

When it happens

Trigger: rtnetlink.Dial(nil) fails when netlink sockets are unavailable: no NETLINK_ROUTE support, seccomp/apparmor/SELinux blocking socket(AF_NETLINK), or a container runtime without netlink in the sandbox.

Common situations: Hardened containers (seccomp profiles blocking netlink); restricted service users without CAP_NET_ADMIN-ish socket permissions; unusual sandboxes/gVisor environments lacking rtnetlink.

Related errors


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

Appendix: source

Thrown at collector/network_route_linux.go:64

	)
	routesDesc := prometheus.NewDesc(
		prometheus.BuildFQName(namespace, subsystem, "routes"),
		"network routes by interface", []string{"device"}, nil,
	)

	return &networkRouteCollector{
		routeInfoDesc: routeInfoDesc,
		routesDesc:    routesDesc,
		logger:        logger,
	}, nil
}

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 {

View on GitHub (pinned to 17ddd77c59)