netbirdio/netbird · error
failed to delete link %s: %w
Error message
failed to delete link %s: %w
What it means
The second half of Linux Destroy(): after the link is resolved, netlink.LinkDel asks the kernel to delete it and this error wraps the failure. Causes: insufficient privilege (EPERM without CAP_NET_ADMIN), the link being busy or referenced (EBUSY), a link type the kernel refuses to delete, or transient netlink socket errors.
Source
Thrown at client/iface/iface_destroy_linux.go:18
//go:build linux && !android
package iface
import (
"fmt"
"github.com/vishvananda/netlink"
)
func (w *WGIface) Destroy() error {
link, err := netlink.LinkByName(w.Name())
if err != nil {
return fmt.Errorf("failed to get link by name %s: %w", w.Name(), err)
}
if err := netlink.LinkDel(link); err != nil {
return fmt.Errorf("failed to delete link %s: %w", w.Name(), err)
}
return nil
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Run `sudo ip link del <name>` to surface the exact errno
- Clear routes and firewall references to the interface, then retry
- Grant CAP_NET_ADMIN or run the daemon as root
- If the kernel keeps refusing (EBUSY), reboot is the last resort
Defensive patterns
Strategy: retry
Try / catch
if err := w.Destroy(); err != nil {
if _, lerr := net.InterfaceByName(w.Name()); lerr == nil {
// still present: transient refusal (EBUSY-class), retry once
err = w.Destroy()
}
return err
} Prevention
- Tear down routes and firewall rules before deleting the link
- Keep the required capabilities on the daemon
- Retry once on EBUSY/EAGAIN-class refusals, then surface the errno
When it happens
Trigger: LinkDel returning EPERM/EBUSY/EINVAL: unprivileged daemon, interface still referenced by routes or firewall rules, or a halfway-removed interface during rapid up/down cycling.
Common situations: Containers with trimmed capabilities; external network daemons re-referencing the interface; repeated teardown/setup cycles racing kernel cleanup.
Related errors
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/c9901ae2db063082.
Report an issue: GitHub.