{"record":{"id":"b0e8575864105af2","repo":"netbirdio/netbird","slug":"received-error-w-while-configuring-interface-s","errorCode":null,"errorMessage":"received error \"%w\" while configuring interface %s with port %d","messagePattern":"received error \"%w\" while configuring interface (.+?) with port (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/iface/configurer/kernel_unix.go","lineNumber":47,"sourceCode":"}\n\nfunc (c *KernelConfigurer) ConfigureInterface(privateKey string, port int) error {\n\tlog.Debugf(\"adding Wireguard private key\")\n\tkey, err := wgtypes.ParseKey(privateKey)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfwmark := getFwmark()\n\tconfig := wgtypes.Config{\n\t\tPrivateKey:   &key,\n\t\tReplacePeers: true,\n\t\tFirewallMark: &fwmark,\n\t\tListenPort:   &port,\n\t}\n\n\terr = c.configure(config)\n\tif err != nil {\n\t\treturn fmt.Errorf(`received error \"%w\" while configuring interface %s with port %d`, err, c.deviceName, port)\n\t}\n\treturn nil\n}\n\n// SetPresharedKey sets the preshared key for a peer.\n// If updateOnly is true, only updates the existing peer; if false, creates or updates.\nfunc (c *KernelConfigurer) SetPresharedKey(peerKey string, psk wgtypes.Key, updateOnly bool) error {\n\tparsedPeerKey, err := wgtypes.ParseKey(peerKey)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcfg := buildPresharedKeyConfig(parsedPeerKey, psk, updateOnly)\n\treturn c.configure(cfg)\n}\n\nfunc (c *KernelConfigurer) UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error {\n\tpeerKeyParsed, err := wgtypes.ParseKey(peerKey)","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/iface/configurer/kernel_unix.go#L29-L65","documentation":"The kernel WireGuard configurer failed to apply the device-level configuration (private key, fwmark, listen port) through wgctrl/netlink on the named interface. The %w chain carries the underlying cause, which in practice is syscall.ENOENT when the interface disappeared, EACCES/EPERM without CAP_NET_ADMIN or root, EADDRINUSE when the listen port is taken, or EINVAL for a bad key/fwmark. The message deliberately names the interface and port because the same error covers several distinct root causes.","triggerScenarios":"The interface was deleted between creation and configuration (race with teardown or external ip link del); agent not running as root or missing CAP_NET_ADMIN; the requested ListenPort already bound by another process; wgctrl kernel socket unavailable in restricted containers/seccomp profiles.","commonSituations":"Running netbird without privileges or in a container lacking NET_ADMIN; another WireGuard instance or the previous unclean shutdown still holding the port; platform uapi/wgctrl regressions after kernel or package upgrades; interface churn during rapid up/down cycles.","solutions":["Check the wrapped syscall: ENOENT means recreate the interface first; EACCES means run privileged; EADDRINUSE means change the port or free it","Verify the agent runs as root or with CAP_NET_ADMIN (container: --cap-add NET_ADMIN)","Ensure only one agent instance manages the interface and previous runs fully tore it down (netbird down / ip link del)","Retry the configure once after recreating the interface when the cause is the teardown race","On port conflicts, let NetBird pick an ephemeral port instead of pining ListenPort"],"exampleFix":"// before\nif err := c.Configure(key, port); err != nil { return err }\n\n// after\nif err := c.Configure(key, port); err != nil {\n    if errors.Is(err, syscall.ENOENT) {\n        // interface vanished; caller recreates it and retries once\n        return fmt.Errorf(\"interface %s gone, recreate: %w\", c.deviceName, err)\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// before configuring, confirm privileges and interface presence\nif os.Geteuid() != 0 {\n    return errors.New(\"kernel WireGuard configuration requires root\")\n}\nif _, err := net.InterfaceByName(ifaceName); err != nil {\n    return fmt.Errorf(\"interface missing, recreate first: %w\", err)\n}","typeGuard":"func kernelWGReady(name string) bool {\n    if _, err := net.InterfaceByName(name); err != nil {\n        return false\n    }\n    client, err := wgctrl.New()\n    if err != nil {\n        return false\n    }\n    defer client.Close()\n    _, err = client.Device(name)\n    return err == nil\n}","tryCatchPattern":"if err := configurer.ConfigureInterface(key, port); err != nil {\n    switch {\n    case errors.Is(err, syscall.ENOENT):\n        // recreate interface and retry once\n    case errors.Is(err, syscall.EADDRINUSE):\n        // pick a different listen port\n    case errors.Is(err, syscall.EACCES), errors.Is(err, syscall.EPERM):\n        return fmt.Errorf(\"need root/CAP_NET_ADMIN: %w\", err)\n    default:\n        return err\n    }\n}","preventionTips":["Run the agent as root or with CAP_NET_ADMIN (containers: --cap-add NET_ADMIN)","Ensure the previous instance fully tore the interface down before a new one configures it","Avoid pinning ListenPort unless required; ephemeral ports dodge EADDRINUSE","Retry once on ENOENT: the delete/configure race is common during rapid restarts"],"tags":["go","netbird","wireguard","kernel","netlink","privileges"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}