netbirdio/netbird · error

link by name: %w

Error message

link by name: %w

What it means

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'.

Source

Thrown at client/iface/device/wg_link_linux.go:55

	return "wireguard"
}

// Close deletes the link interface
func (l *wgLink) Close() error {
	return netlink.LinkDel(l)
}

func (l *wgLink) recreate() error {
	name := l.attrs.Name

	// check if interface exists
	link, err := netlink.LinkByName(name)
	if err != nil {
		switch err.(type) {
		case netlink.LinkNotFoundError:
			break
		default:
			return fmt.Errorf("link by name: %w", err)
		}
	}

	// remove if interface exists
	if link != nil {
		err = netlink.LinkDel(l)
		if err != nil {
			return err
		}
	}

	log.Debugf("adding device: %s", name)
	err = netlink.LinkAdd(l)
	if os.IsExist(err) {
		log.Infof("interface %s already exists. Will reuse.", name)
	} else if err != nil {
		return fmt.Errorf("link add: %w", err)
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Run with root/CAP_NET_ADMIN
  2. Inspect the wrapped errno to identify the specific netlink failure
  3. Retry once; transient rtnetlink errors occur during interface churn
  4. Check whether another process deletes interfaces at that moment

Example fix

// before
switch err.(type) {
case netlink.LinkNotFoundError:
	break
default:
	return fmt.Errorf("link by name: %w", err)
}

// after
var lnf netlink.LinkNotFoundError
if errors.As(err, &lnf) {
	// interface absent: proceed to create
} else if err != nil {
	return fmt.Errorf("link by name: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: privileges and netlink availability
if os.Geteuid() != 0 {
    log.Warn("netlink operations require root or CAP_NET_ADMIN")
}

Type guard

var linkNotFound netlink.LinkNotFoundError
if errors.As(err, &linkNotFound) {
    // benign: interface absent, recreate will create it
} else if err != nil {
    // real netlink failure (permission, protocol)
}

Try / catch

if _, err := netlink.LinkByName(name); err != nil {
    var lnf netlink.LinkNotFoundError
    if !errors.As(err, &lnf) {
        return fmt.Errorf("link by name: %w", err) // unexpected netlink failure
    }
    // not found: proceed to create
}

Prevention

When it happens

Trigger: Running without CAP_NET_ADMIN (EPERM on the netlink operation), netlink socket exhaustion, transient rtnetlink errors during heavy interface churn, udev/NetworkManager races.

Common situations: Agent started as an unprivileged user, containers missing NET_ADMIN, early boot before rtnetlink is fully settled.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/b12101bd137b3264. Report an issue: GitHub.