{"record":{"id":"9098171fab720b31","repo":"prometheus/node_exporter","slug":"couldn-t-get-routes-w","errorCode":null,"errorMessage":"couldn't get routes: %w","messagePattern":"couldn't get routes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/network_route_linux.go","lineNumber":75,"sourceCode":"}\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\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlabels := []string{\n\t\t\t\t\tifName, // if","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/network_route_linux.go#L57-L93","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Retry the scrape; large-table ENOBUFS failures are sometimes transient.","Increase netlink dump buffer capacity by updating mdlayher/netlink/rtnetlink (or adjust socket buffers via syscall).","Trim the routing table size on the host if it's unexpectedly large.","Update node_exporter and its netlink dependencies; report persistent parse errors upstream with `ip route | wc -l` and kernel version."],"exampleFix":"// before\nroutes, err := conn.Route.List()\nif err != nil {\n\treturn fmt.Errorf(\"couldn't get routes: %w\", err)\n}\n// after (add table-size context for diagnosing buffer overflows)\nroutes, err := conn.Route.List()\nif err != nil {\n\treturn fmt.Errorf(\"couldn't get routes (large routing table may exceed netlink buffer): %w\", err)\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"// Retry once; then report with table-size context\nroutes, err := conn.Route.List()\nif err != nil {\n\ttime.Sleep(50 * time.Millisecond)\n\tif routes, err = conn.Route.List(); err != nil {\n\t\treturn fmt.Errorf(\"couldn't get routes: %w\", err)\n\t}\n}","preventionTips":["Update netlink libraries for larger default dump buffers on big routing tables.","Monitor routing table size; oversized tables (BGP full tables) stress netlink dumps.","Retry-based alerting: only alert after consecutive scrape failures.","Confirm parse compatibility by testing the exporter against your kernel version before rollout."],"tags":["linux","netlink","rtnetlink","routes","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"}