netbirdio/netbird · error
received error "%w" while removing peer %s from interface %s
Error message
received error "%w" while removing peer %s from interface %s
What it means
The kernel configurer failed to remove a peer from the named WireGuard interface via wgctrl/netlink. The %w chain holds the actual cause: ENOENT when the device (or on some wgctrl versions the peer) no longer exists, EACCES/EPERM without privileges, or a netlink/uapi transport error. The peer key and interface name are embedded to identify the exact removal that failed.
Source
Thrown at client/iface/configurer/kernel_unix.go:143
}
func (c *KernelConfigurer) RemovePeer(peerKey string) error {
peerKeyParsed, err := wgtypes.ParseKey(peerKey)
if err != nil {
return err
}
peer := wgtypes.PeerConfig{
PublicKey: peerKeyParsed,
Remove: true,
}
config := wgtypes.Config{
Peers: []wgtypes.PeerConfig{peer},
}
err = c.configure(config)
if err != nil {
return fmt.Errorf(`received error "%w" while removing peer %s from interface %s`, err, peerKey, c.deviceName)
}
return nil
}
func (c *KernelConfigurer) AddAllowedIP(peerKey string, allowedIP netip.Prefix) error {
ipNet := net.IPNet{
IP: allowedIP.Addr().AsSlice(),
Mask: net.CIDRMask(allowedIP.Bits(), allowedIP.Addr().BitLen()),
}
peerKeyParsed, err := wgtypes.ParseKey(peerKey)
if err != nil {
return err
}
peer := wgtypes.PeerConfig{
PublicKey: peerKeyParsed,
UpdateOnly: true,
ReplaceAllowedIPs: false,View on GitHub (pinned to 93e97f4bf1)
Solutions
- Classify the wrapped error: device/peer-missing is effectively success for a removal, so absorb it; permission errors need a privilege fix
- Make removal idempotent by checking getPeer first or tolerating the not-found cause in the caller
- Serialize peer removal with interface lifecycle events so removals never target a torn-down device
- Verify with wg show <if> that the peer actually remains if the error was a transport failure, then retry
Example fix
// before
if err := c.RemovePeer(peerKey); err != nil { return err }
// after
if err := c.RemovePeer(peerKey); err != nil {
if errors.Is(err, syscall.ENOENT) {
return nil // already gone; desired state reached
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
client, err := wgctrl.New()
if err != nil { return err }
device, err := client.Device(deviceName)
if err != nil { return err }
for _, p := range device.Peers {
if p.PublicKey.String() == peerKey {
// present: proceed with removal
}
} Type guard
func peerOnDevice(deviceName, peerKey string) (bool, error) {
client, err := wgctrl.New()
if err != nil {
return false, err
}
defer client.Close()
d, err := client.Device(deviceName)
if err != nil {
return false, err
}
for _, p := range d.Peers {
if p.PublicKey.String() == peerKey {
return true, nil
}
}
return false, nil
} Try / catch
if err := configurer.RemovePeer(peerKey); err != nil {
if errors.Is(err, syscall.ENOENT) {
return nil // device or peer already gone: desired state
}
return fmt.Errorf("remove peer %s: %w", peerKey, err)
} Prevention
- Treat not-found as success: peer removal should be idempotent
- Deduplicate peer-removal events from the network map before they reach the configurer
- Serialize removals with interface lifecycle so they never target a torn-down device
- Verify with wg show after a transport-flavored failure, then retry once
When it happens
Trigger: Removing a peer after the interface was deleted or fully resynced with ReplacePeers (peer already gone); concurrent teardown during engine shutdown; running without CAP_NET_ADMIN; uapi socket unavailable in restricted environments.
Common situations: Network map changes (peer left a group) racing engine restarts; duplicate peer-removal events processed twice; unclean previous shutdowns leaving the device state out of sync with what the configurer expects.
Related errors
- received error "%w" while updating peer on interface %s with
- received error "%w" while configuring interface %s with port
- get peer: %w
- error removing peer %s from interface %s: %w
- error re-adding peer %s to interface %s with allowed IPs %v:
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/957891e6d6ed1c43.
Report an issue: GitHub.