{"record":{"id":"164068af7114f5cd","repo":"prometheus/node_exporter","slug":"couldn-t-get-links-w","errorCode":null,"errorMessage":"couldn't get links: %w","messagePattern":"couldn't get links: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/network_route_linux.go","lineNumber":70,"sourceCode":"\treturn &networkRouteCollector{\n\t\trouteInfoDesc: routeInfoDesc,\n\t\troutesDesc:    routesDesc,\n\t\tlogger:        logger,\n\t}, nil\n}\n\nfunc (n networkRouteCollector) Update(ch chan<- prometheus.Metric) error {\n\tdeviceRoutes := make(map[string]int)\n\n\tconn, err := rtnetlink.Dial(nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"couldn't connect rtnetlink: %w\", err)\n\t}\n\tdefer conn.Close()\n\n\tlinks, err := conn.Link.List()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"couldn't get links: %w\", err)\n\t}\n\n\troutes, err := conn.Route.List()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"couldn't get routes: %w\", err)\n\t}\n\n\tfor _, route := range routes {\n\t\tif route.Type != unix.RTA_DST {\n\t\t\tcontinue\n\t\t}\n\t\tif len(route.Attributes.Multipath) != 0 {\n\t\t\tfor _, nextHop := range route.Attributes.Multipath {\n\t\t\t\tifName := \"\"\n\t\t\t\tfor _, link := range links {\n\t\t\t\t\tif link.Index == nextHop.Hop.IfIndex {\n\t\t\t\t\t\tifName = link.Attributes.Name\n\t\t\t\t\t\tbreak","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/network_route_linux.go#L52-L88","documentation":"After successfully connecting to rtnetlink, the network_route collector lists all network links via conn.Link.List(). If the netlink dump or its parsing fails, Update returns this wrapped error and no route metrics are emitted for the scrape.","triggerScenarios":"conn.Link.List() fails on netlink dump errors (socket closed mid-dump, buffer too small for a very large number of links, kernel/netlink message parse failure from mdlayher/netlink).","commonSituations":"Transient netlink buffer overflows on hosts with thousands of interfaces (many veth/containers); kernel bugs; intermittent netlink EBUSY/ENOBUFS under heavy interface churn.","solutions":["Retry the scrape; transient netlink dump failures often resolve on the next scrape.","Reduce interface churn or count on the host (clean up orphaned veth devices).","Update mdlayher/netlink, mdlayher/rtnetlink, and node_exporter to get buffer/parse fixes.","Check kernel logs for netlink errors; if persistent with many links, report upstream."],"exampleFix":"// before\nlinks, err := conn.Link.List()\nif err != nil {\n\treturn fmt.Errorf(\"couldn't get links: %w\", err)\n}\n// after (one retry on transient failure)\nlinks, err := conn.Link.List()\nif err != nil {\n\tlinks, err = conn.Link.List()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"couldn't get links: %w\", err)\n\t}\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"// Retry transient netlink dump failures once before failing the scrape\nlinks, err := conn.Link.List()\nif err != nil {\n\ttime.Sleep(50 * time.Millisecond)\n\tif links, err = conn.Link.List(); err != nil {\n\t\treturn fmt.Errorf(\"couldn't get links: %w\", err)\n\t}\n}","preventionTips":["Keep mdlayher/netlink and mdlayher/rtnetlink updated for dump robustness fixes.","Watch for ENOBUFS-style failures on hosts with thousands of interfaces.","Reduce veth/interface churn on busy container hosts.","Alert on repeated node_scrape_collector_success{collector=\"network_route\"}==0 rather than single failures."],"tags":["linux","netlink","rtnetlink","network"],"backgroundTag":"network-request-failed","analyzedSha":"17ddd77c59ba27e1508e9f7894b1e55b44d6aed3","analyzedAt":"2026-09-07T17:54:06.211Z","contentChangedAt":"2026-09-07T17:54:06.211Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}