{"record":{"id":"2799644f2d5743de","repo":"netbirdio/netbird","slug":"failed-to-remove-peer-s","errorCode":null,"errorMessage":"failed to remove peer: %s","messagePattern":"failed to remove peer: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/iface/configurer/usp.go","lineNumber":172,"sourceCode":"\t\t\tfound = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !found {\n\t\treturn fmt.Errorf(\"peer %s not found\", peerKey)\n\t}\n\n\t// remove the peer from the WireGuard configuration\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\tif ipcErr := c.device.IpcSet(toWgUserspaceString(config)); ipcErr != nil {\n\t\treturn fmt.Errorf(\"failed to remove peer: %s\", ipcErr)\n\t}\n\n\t// Build the peer config\n\tpeer = wgtypes.PeerConfig{\n\t\tPublicKey:         peerKeyParsed,\n\t\tReplaceAllowedIPs: true,\n\t\tAllowedIPs:        allowedIPs,\n\t}\n\n\tconfig = wgtypes.Config{\n\t\tPeers: []wgtypes.PeerConfig{peer},\n\t}\n\n\tif err := c.device.IpcSet(toWgUserspaceString(config)); err != nil {\n\t\treturn fmt.Errorf(\"remove endpoint address: %w\", err)\n\t}\n\n\treturn nil","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/iface/configurer/usp.go#L154-L190","documentation":"The first phase of WGUSPConfigurer.RemoveEndpointAddress, an IpcSet with remove=true, failed, so the peer could not be removed before being re-added without an endpoint. wireguard-go rejects the removal mainly when the device is closed or the generated UAPI line is malformed. Note the message formats with %s instead of %w, so errors.Is/As cannot see the underlying cause through this wrapper.","triggerScenarios":"Device closed or closing when IpcSet(remove=true) runs; public key serialized incorrectly into the public_key= line; a wireguard-go internal state error surfaced by IpcSet.","commonSituations":"Endpoint cleanup racing device Close during shutdown; version-skewed wireguard-go rejecting a line the builder emits; tests driving the configurer against a fake device that errors on IpcSet.","solutions":["Ensure the device is still running before mutating peers; skip cleanup after Close","Change the wrapper to %w so callers can branch on the real cause (upstream fix)","Log the raw ipcErr string since no wrapping is currently preserved","Retry once if the failure coincided with a device restart"],"exampleFix":"// before: %s destroys the error chain\nreturn fmt.Errorf(\"failed to remove peer: %s\", ipcErr)\n\n// after: wrap with %w\nreturn fmt.Errorf(\"remove peer %s: %w\", peerKey, ipcErr)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := uspCfg.RemoveEndpointAddress(peerKey); err != nil {\n\t// NOTE: this error wraps with %s upstream, so errors.Is will not match the cause;\n\t// match on message text or fix the wrapper to %w\n\tif strings.Contains(err.Error(), \"failed to remove peer\") {\n\t\t// device likely closed mid-operation: verify lifecycle, then retry once if alive\n\t}\n\treturn err\n}","preventionTips":["Use %w (not %s) when wrapping IpcSet errors so errors.Is/As keep working","Verify the device is running before two-phase peer mutations","Serialize IpcSet sequences per peer to avoid interleaved remove/re-add","Include the peer key in the message to make logs actionable"],"tags":["wireguard-go","uapi","error-wrapping","lifecycle","userspace"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}