netbirdio/netbird · error

get peer: %w

Error message

get peer: %w

What it means

RemoveEndpointAddress first reads the current peer state via getPeer so it can preserve the allowed IPs when re-adding the peer without its endpoint. That read failed, which on the kernel path means wgctrl could not return the peer: the device does not exist (ENOENT), the peer key is not present on the device, or the netlink/uapi transport errored (permissions, interrupted syscall).

Source

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

		Peers: []wgtypes.PeerConfig{peer},
	}
	err = c.configure(config)
	if err != nil {
		return fmt.Errorf(`received error "%w" while updating peer on interface %s with settings: allowed ips %s, endpoint %s`, err, c.deviceName, allowedIps, endpoint.String())
	}
	return nil
}

func (c *KernelConfigurer) RemoveEndpointAddress(peerKey string) error {
	peerKeyParsed, err := wgtypes.ParseKey(peerKey)
	if err != nil {
		return err
	}

	// Get the existing peer to preserve its allowed IPs
	existingPeer, err := c.getPeer(c.deviceName, peerKey)
	if err != nil {
		return fmt.Errorf("get peer: %w", err)
	}

	removePeerCfg := wgtypes.PeerConfig{
		PublicKey: peerKeyParsed,
		Remove:    true,
	}

	if err := c.configure(wgtypes.Config{Peers: []wgtypes.PeerConfig{removePeerCfg}}); err != nil {
		return fmt.Errorf(`error removing peer %s from interface %s: %w`, peerKey, c.deviceName, err)
	}

	//Re-add the peer without the endpoint but same AllowedIPs
	reAddPeerCfg := wgtypes.PeerConfig{
		PublicKey:         peerKeyParsed,
		AllowedIPs:        existingPeer.AllowedIPs,
		ReplaceAllowedIPs: true,
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Treat unknown-peer/device causes as idempotent success when the goal state is 'peer without endpoint', instead of propagating the error
  2. Retry once after confirming the interface still exists (ip link show / wg show) before failing the operation
  3. Serialize remove operations with device resync so ReplacePeers cannot wipe the peer mid-operation
  4. Check the wrapped wgctrl error text to distinguish 'no such device' from 'no such peer'

Example fix

// before
existingPeer, err := c.getPeer(c.deviceName, peerKey)
if err != nil { return fmt.Errorf("get peer: %w", err) }

// after
existingPeer, err := c.getPeer(c.deviceName, peerKey)
if err != nil {
    if isPeerOrDeviceGone(err) {
        return nil // desired state already reached
    }
    return fmt.Errorf("get peer: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// confirm the peer exists before endpoint removal
if _, err := getPeer(deviceName, peerKey); err != nil {
    if isNotFound(err) {
        return nil // nothing to remove; desired state
    }
    return err
}

Type guard

func peerExists(deviceName, peerKey string) bool {
    client, err := wgctrl.New()
    if err != nil {
        return false
    }
    defer client.Close()
    d, err := client.Device(deviceName)
    if err != nil {
        return false
    }
    for _, p := range d.Peers {
        if p.PublicKey.String() == peerKey {
            return true
        }
    }
    return false
}

Try / catch

if err := configurer.RemoveEndpointAddress(peerKey); err != nil {
    if strings.Contains(err.Error(), "get peer") && isNotFound(err) {
        return nil // idempotent success
    }
    return err
}

Prevention

When it happens

Trigger: Removing an endpoint for a peer that was already removed from the device (e.g. after a ReplacePeers configure or full peer resync); the interface being torn down concurrently; an invalid peer public key string that fails wgtypes.ParseKey earlier or a device enumeration failure under load.

Common situations: Engine reconfiguration flows (network map change, peer removal from group) racing a full device re-setup; duplicated removal requests where the first one already succeeded; unclean prior shutdown leaving the configurer pointing at a dead device.

Related errors


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