netbirdio/netbird · error

get device %s: %w

Error message

get device %s: %w

What it means

Inside getPeer, wg.Device(ifaceName) failed. wgctrl returns an error wrapping os.ErrNotExist (ENODEV) when the named interface does not exist or is not a WireGuard device, and other netlink errors for transport problems. It surfaces wrapped as 'get peer: get device <name>: ...' from RemoveAllowedIP and RemoveEndpointAddress.

Source

Thrown at client/iface/configurer/kernel_unix.go:231

	}
	return nil
}

func (c *KernelConfigurer) getPeer(ifaceName, peerPubKey string) (wgtypes.Peer, error) {
	wg, err := wgctrl.New()
	if err != nil {
		return wgtypes.Peer{}, fmt.Errorf("wgctl: %w", err)
	}
	defer func() {
		err = wg.Close()
		if err != nil {
			log.Errorf("Got error while closing wgctl: %v", err)
		}
	}()

	wgDevice, err := wg.Device(ifaceName)
	if err != nil {
		return wgtypes.Peer{}, fmt.Errorf("get device %s: %w", ifaceName, err)
	}
	for _, peer := range wgDevice.Peers {
		if peer.PublicKey.String() == peerPubKey {
			return peer, nil
		}
	}
	return wgtypes.Peer{}, ErrPeerNotFound
}

func (c *KernelConfigurer) configure(config wgtypes.Config) error {
	wg, err := wgctrl.New()
	if err != nil {
		return err
	}
	defer func() {
		if err := wg.Close(); err != nil {
			log.Errorf("Failed to close wgctrl client: %v", err)
		}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Confirm the interface exists and is WireGuard: sudo wg show <deviceName>
  2. Recreate the interface before reconfiguring peers if it was torn down
  3. Match on errors.Is(err, os.ErrNotExist) and treat the peer operation as a no-op when the device is gone
  4. Check for name mismatches when a custom interface name is configured
Defensive patterns

Strategy: validation

Validate before calling

// confirm the interface exists and is a WireGuard device before peer ops
func wgDeviceExists(name string) bool {
	if _, err := net.InterfaceByName(name); err != nil {
		return false
	}
	wg, err := wgctrl.New()
	if err != nil {
		return false
	}
	defer wg.Close()
	_, err = wg.Device(name)
	return err == nil
}

Try / catch

if err := kernelCfg.RemoveAllowedIP(peerKey, prefix); err != nil {
	if errors.Is(err, os.ErrNotExist) {
		return nil // device gone: nothing left to configure
	}
	return err
}

Prevention

When it happens

Trigger: Interface name typo or renamed device; interface deleted before the peer lookup; device exists but was created by a non-WireGuard driver; netlink transport error mid-query.

Common situations: NetBird interface (default wt0) already torn down when a route removal runs; custom interface name configured inconsistently between creation and configurer; agents in environments where another tool removed the link.

Related errors


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