{"record":{"id":"957891e6d6ed1c43","repo":"netbirdio/netbird","slug":"received-error-w-while-removing-peer-s-from-in","errorCode":null,"errorMessage":"received error \"%w\" while removing peer %s from interface %s","messagePattern":"received error \"%w\" while removing peer (.+?) from interface (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/iface/configurer/kernel_unix.go","lineNumber":143,"sourceCode":"}\n\nfunc (c *KernelConfigurer) RemovePeer(peerKey string) error {\n\tpeerKeyParsed, err := wgtypes.ParseKey(peerKey)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tpeer := wgtypes.PeerConfig{\n\t\tPublicKey: peerKeyParsed,\n\t\tRemove:    true,\n\t}\n\n\tconfig := wgtypes.Config{\n\t\tPeers: []wgtypes.PeerConfig{peer},\n\t}\n\terr = c.configure(config)\n\tif err != nil {\n\t\treturn fmt.Errorf(`received error \"%w\" while removing peer %s from interface %s`, err, peerKey, c.deviceName)\n\t}\n\treturn nil\n}\n\nfunc (c *KernelConfigurer) AddAllowedIP(peerKey string, allowedIP netip.Prefix) error {\n\tipNet := net.IPNet{\n\t\tIP:   allowedIP.Addr().AsSlice(),\n\t\tMask: net.CIDRMask(allowedIP.Bits(), allowedIP.Addr().BitLen()),\n\t}\n\n\tpeerKeyParsed, err := wgtypes.ParseKey(peerKey)\n\tif err != nil {\n\t\treturn err\n\t}\n\tpeer := wgtypes.PeerConfig{\n\t\tPublicKey:         peerKeyParsed,\n\t\tUpdateOnly:        true,\n\t\tReplaceAllowedIPs: false,","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/iface/configurer/kernel_unix.go#L125-L161","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nif err := c.RemovePeer(peerKey); err != nil { return err }\n\n// after\nif err := c.RemovePeer(peerKey); err != nil {\n    if errors.Is(err, syscall.ENOENT) {\n        return nil // already gone; desired state reached\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"client, err := wgctrl.New()\nif err != nil { return err }\ndevice, err := client.Device(deviceName)\nif err != nil { return err }\nfor _, p := range device.Peers {\n    if p.PublicKey.String() == peerKey {\n        // present: proceed with removal\n    }\n}","typeGuard":"func peerOnDevice(deviceName, peerKey string) (bool, error) {\n    client, err := wgctrl.New()\n    if err != nil {\n        return false, err\n    }\n    defer client.Close()\n    d, err := client.Device(deviceName)\n    if err != nil {\n        return false, err\n    }\n    for _, p := range d.Peers {\n        if p.PublicKey.String() == peerKey {\n            return true, nil\n        }\n    }\n    return false, nil\n}","tryCatchPattern":"if err := configurer.RemovePeer(peerKey); err != nil {\n    if errors.Is(err, syscall.ENOENT) {\n        return nil // device or peer already gone: desired state\n    }\n    return fmt.Errorf(\"remove peer %s: %w\", peerKey, err)\n}","preventionTips":["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"],"tags":["go","netbird","wireguard","kernel","netlink","peers"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}