netbirdio/netbird · error
remove allowed IP %s on interface %s: %w
Error message
remove allowed IP %s on interface %s: %w
What it means
RemoveAllowedIP rebuilt the peer's allowed-IP list without the target prefix and asked the kernel to replace the peer's allowed IPs (ReplaceAllowedIPs:true, UpdateOnly:true), but wg.ConfigureDevice returned an error. Because the whole list is swapped in one netlink operation, one invalid surviving entry, a vanished peer or interface, or a permission problem aborts the removal. The wrapped netlink error names the concrete cause.
Source
Thrown at client/iface/configurer/kernel_unix.go:212
if existingAllowedIP.String() == ipNet.String() {
newAllowedIPs = append(existingPeer.AllowedIPs[:i], existingPeer.AllowedIPs[i+1:]...) //nolint:gocritic
break
}
}
peer := wgtypes.PeerConfig{
PublicKey: peerKeyParsed,
UpdateOnly: true,
ReplaceAllowedIPs: true,
AllowedIPs: newAllowedIPs,
}
config := wgtypes.Config{
Peers: []wgtypes.PeerConfig{peer},
}
err = c.configure(config)
if err != nil {
return fmt.Errorf("remove allowed IP %s on interface %s: %w", allowedIP, c.deviceName, err)
}
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 {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Read the wrapped error: ENOENT means peer/interface vanished (safe to ignore), EINVAL means a bad allowed IP, EPERM means privileges
- Serialize peer reconfigurations with a per-peer or per-interface mutex to avoid remove/rebuild races
- Re-check with FullStats and retry once if the peer still exists
- Run with CAP_NET_ADMIN and confirm the device with wg show
Defensive patterns
Strategy: try-catch
Try / catch
if err := kernelCfg.RemoveAllowedIP(peerKey, prefix); err != nil {
if errors.Is(err, os.ErrNotExist) {
// peer/interface vanished mid-operation; safe to treat as removed
return nil
}
if errors.Is(err, os.ErrPermission) {
// escalate: daemon lost privileges, do not retry
return err
}
// EINVAL-style netlink rejection: dump current peers and investigate
return err
} Prevention
- Serialize per-peer reconfiguration with a mutex to avoid rebuild races
- Re-read peer state and retry once when the wrapped error indicates a vanished peer
- Validate allowed-IP prefixes with netip.ParsePrefix before they ever reach the device
- Run with CAP_NET_ADMIN so EPERM never masquerades as a config bug
When it happens
Trigger: Peer removed concurrently between getPeer and configure (UpdateOnly:true then hits a missing peer); device deleted mid-call; an allowed-IP entry in the existing list rejected by netlink validation; EPERM without CAP_NET_ADMIN.
Common situations: Two goroutines reconfiguring the same peer during a network-map roll; interface teardown racing a route removal; running without root in a test harness that created the device earlier.
Related errors
- received error "%w" while adding allowed Ip to peer on inter
- get device %s: %w
- received error "%w" while configuring interface %s with port
- received error "%w" while updating peer on interface %s with
- received error "%w" while removing peer %s from interface %s
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/40d818721f8f8116.
Report an issue: GitHub.