{"record":{"id":"2411fe11214f5058","repo":"slackhq/nebula","slug":"unable-to-discover-link-addr-for-tun-interface-2411fe","errorCode":null,"errorMessage":"unable to discover link_addr for tun interface","messagePattern":"unable to discover link_addr for tun interface","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"overlay/tun_freebsd.go","lineNumber":486,"sourceCode":"\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"unknown address type %v\", cidr)\n}\n\nfunc (t *tun) Activate() error {\n\t// Setup our default MTU\n\terr := t.setMTU()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlinkAddr, err := getLinkAddr(t.Device)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif linkAddr == nil {\n\t\treturn fmt.Errorf(\"unable to discover link_addr for tun interface\")\n\t}\n\tt.linkAddr = linkAddr\n\n\tfor i := range t.vpnNetworks {\n\t\terr := t.addIp(t.vpnNetworks[i])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn t.addRoutes(false)\n}\n\nfunc (t *tun) setMTU() error {\n\t// Set the MTU on the device\n\ts, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)\n\tif err != nil {\n\t\treturn err","sourceCodeStart":468,"sourceCodeEnd":504,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tun_freebsd.go#L468-L504","documentation":"Activate() looks up the link-layer address (MAC/link_addr) of the tun interface by device name before assigning IPs. If getLinkAddr succeeds but returns no entry, the interface does not exist in the system interface list, and this error is returned. It is not wrapped because the plain-text cause is the whole story: no link_addr could be discovered for t.Device.","triggerScenarios":"getLinkAddr(t.Device) returns (nil, nil) — the interface name configured for the tun (e.g. from config 'dev' / 'tun') does not correspond to any existing interface at the time Activate runs.","commonSituations":"Config points at a device name that was never created (e.g. 'tun0' when the kernel allocated 'tun1'); the device was destroyed between open and Activate; running in a jail/vnet without the tun interface visible; name mismatch after OS upgrade.","solutions":["Verify the interface exists: run `ifconfig` and match the configured device name exactly","Don't hardcode the tun name in config; let the library open the next free device and use its reported Device","Check jail/vnet confinement — the interface may exist on the host but not in the jail's network stack","Re-run device creation if the interface was torn down; ensure Activate is called right after newTun"],"exampleFix":"// before\n# config\ntun: tun9   # device may not exist\n// after\n# omit explicit device name or verify with:\n_, err := net.InterfaceByName(\"tun9\")\nif err != nil { /* recreate device or clear config */ }","handlingStrategy":"validation","validationCode":"if _, err := net.InterfaceByName(deviceName); err != nil {\n    return fmt.Errorf(\"tun device %q does not exist before Activate: %w\", deviceName, err)\n}","typeGuard":null,"tryCatchPattern":"if err := dev.Activate(); err != nil {\n    if strings.Contains(err.Error(), \"unable to discover link_addr\") {\n        return fmt.Errorf(\"tun interface missing (name mismatch or destroyed): %w\", err)\n    }\n    return err\n}","preventionTips":["Don't hardcode tun names in config; let the library pick and report the device","Call Activate immediately after newTun to avoid races with device teardown","Check jail/vnet visibility of the interface when running confined","Verify with `ifconfig` that the configured device name exists exactly"],"tags":["freebsd","tun","interface-lookup","network-config"],"backgroundTag":"interface-not-found","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"}