{"record":{"id":"b12101bd137b3264","repo":"netbirdio/netbird","slug":"link-by-name-w-b12101","errorCode":null,"errorMessage":"link by name: %w","messagePattern":"link by name: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/iface/device/wg_link_linux.go","lineNumber":55,"sourceCode":"\treturn \"wireguard\"\n}\n\n// Close deletes the link interface\nfunc (l *wgLink) Close() error {\n\treturn netlink.LinkDel(l)\n}\n\nfunc (l *wgLink) recreate() error {\n\tname := l.attrs.Name\n\n\t// check if interface exists\n\tlink, err := netlink.LinkByName(name)\n\tif err != nil {\n\t\tswitch err.(type) {\n\t\tcase netlink.LinkNotFoundError:\n\t\t\tbreak\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"link by name: %w\", err)\n\t\t}\n\t}\n\n\t// remove if interface exists\n\tif link != nil {\n\t\terr = netlink.LinkDel(l)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tlog.Debugf(\"adding device: %s\", name)\n\terr = netlink.LinkAdd(l)\n\tif os.IsExist(err) {\n\t\tlog.Infof(\"interface %s already exists. Will reuse.\", name)\n\t} else if err != nil {\n\t\treturn fmt.Errorf(\"link add: %w\", err)\n\t}","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/iface/device/wg_link_linux.go#L37-L73","documentation":"During linux wgLink.recreate(), netlink.LinkByName(name) failed with an error other than netlink.LinkNotFoundError, which the type-switch tolerates as 'does not exist, will create'. So this wrap is reserved for unexpected rtnetlink failures: permission errors, socket problems, or protocol-level errors. Note the code type-switches on the error instead of errors.As, but the semantics are 'lookup broke', not 'interface missing'.","triggerScenarios":"Running without CAP_NET_ADMIN (EPERM on the netlink operation), netlink socket exhaustion, transient rtnetlink errors during heavy interface churn, udev/NetworkManager races.","commonSituations":"Agent started as an unprivileged user, containers missing NET_ADMIN, early boot before rtnetlink is fully settled.","solutions":["Run with root/CAP_NET_ADMIN","Inspect the wrapped errno to identify the specific netlink failure","Retry once; transient rtnetlink errors occur during interface churn","Check whether another process deletes interfaces at that moment"],"exampleFix":"// before\nswitch err.(type) {\ncase netlink.LinkNotFoundError:\n\tbreak\ndefault:\n\treturn fmt.Errorf(\"link by name: %w\", err)\n}\n\n// after\nvar lnf netlink.LinkNotFoundError\nif errors.As(err, &lnf) {\n\t// interface absent: proceed to create\n} else if err != nil {\n\treturn fmt.Errorf(\"link by name: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"// pre-flight: privileges and netlink availability\nif os.Geteuid() != 0 {\n    log.Warn(\"netlink operations require root or CAP_NET_ADMIN\")\n}","typeGuard":"var linkNotFound netlink.LinkNotFoundError\nif errors.As(err, &linkNotFound) {\n    // benign: interface absent, recreate will create it\n} else if err != nil {\n    // real netlink failure (permission, protocol)\n}","tryCatchPattern":"if _, err := netlink.LinkByName(name); err != nil {\n    var lnf netlink.LinkNotFoundError\n    if !errors.As(err, &lnf) {\n        return fmt.Errorf(\"link by name: %w\", err) // unexpected netlink failure\n    }\n    // not found: proceed to create\n}","preventionTips":["Run with CAP_NET_ADMIN for all rtnetlink operations","Distinguish LinkNotFoundError from real netlink errors with errors.As","Retry once on transient rtnetlink errors during interface churn"],"tags":["linux","netlink","interface","permissions","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}