{"record":{"id":"b8a429dacf93aa59","repo":"slackhq/nebula","slug":"failed-to-get-tun-address-list-s","errorCode":null,"errorMessage":"failed to get tun address list: %s","messagePattern":"failed to get tun address list: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"overlay/tun_linux.go","lineNumber":418,"sourceCode":"\t//add all new addresses\n\tfor i := range newAddrs {\n\t\t//AddrReplace still adds new IPs, but if their properties change it will change them as well\n\t\tif err := netlink.AddrReplace(link, newAddrs[i]); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t//iterate over remainder, remove whoever shouldn't be there\n\tal, err := netlink.AddrList(link, netlink.FAMILY_ALL)\n\tif err != nil {\n\t\t//RTM_GETADDR dumps the whole system, so any concurrent address change\n\t\t//interrupts it - including the kernel's async tentative->preferred\n\t\t//flip of an IPv6 address the AddrReplace calls above just added,\n\t\t//which makes this a race against our own setup. Partial results are\n\t\t//still returned; the worst case is a stale address surviving until\n\t\t//the next config reload, which beats failing startup over it.\n\t\tif !errors.Is(err, netlink.ErrDumpInterrupted) {\n\t\t\treturn fmt.Errorf(\"failed to get tun address list: %s\", err)\n\t\t}\n\t\tt.l.Warn(\"tun address list dump was interrupted, stale addresses may remain\")\n\t}\n\n\tfor i := range al {\n\t\tif hasNetlinkAddr(newAddrs, al[i]) {\n\t\t\tcontinue\n\t\t}\n\t\terr = netlink.AddrDel(link, &al[i])\n\t\tif err != nil {\n\t\t\tt.l.Error(\"failed to remove address from tun address list\", \"error\", err)\n\t\t} else {\n\t\t\tt.l.Info(\"removed address not listed in cert(s)\", \"removed\", al[i].String())\n\t\t}\n\t}\n\n\treturn nil\n}","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tun_linux.go#L400-L436","documentation":"Raised in tun.addIPs (called from Activate) when a netlink dump of the tun device's current address list fails with an error other than netlink.ErrDumpInterrupted. Nebula deliberately tolerates interrupted dumps (it logs a warning and proceeds with partial results), so this error means the address enumeration genuinely failed and stale addresses can't be reconciled.","triggerScenarios":"Calling Activate() when netlink.AddrList (or equivalent dump) on the tun link returns a non-ErrDumpInterrupted error — e.g. the link disappeared, netlink socket errors, or permission problems.","commonSituations":"Race where the tun device was removed/recreated mid-activation; netlink buffer too small (ENOSPC) for many addresses; restricted environments (some sandboxes) blocking netlink RTM_GETADDR dumps.","solutions":["Check the %s error text for the netlink errno (e.g. ENOSPC, ENODEV) and fix the underlying cause.","Verify the tun device still exists (ip link show <dev>) before activating; recreate if removed.","Increase netlink dump buffer / reduce address count if ENOSPC is reported.","Retry Activate() — transient netlink EAGAIN/interference is often temporary.","Ensure the process runs with CAP_NET_ADMIN so netlink dumps are permitted."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"link, err := netlink.LinkByName(dev)\nif err != nil { return fmt.Errorf(\"tun %s missing before activate: %w\", dev, err) }\nif _, err := netlink.AddrList(link, netlink.FAMILY_ALL); err != nil {\n    return fmt.Errorf(\"netlink addr dump unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := activate(); err != nil {\n    if strings.Contains(err.Error(), \"failed to get tun address list\") {\n        time.Sleep(500 * time.Millisecond); err = activate() // one retry\n    }\n}","preventionTips":["Confirm the tun interface exists before activating","Run with CAP_NET_ADMIN so netlink dumps are allowed","Keep address counts modest to avoid netlink dump ENOSPC"],"tags":["network","tun","linux","netlink"],"backgroundTag":"netlink-dump-failed","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}