netbirdio/netbird · error
wgctl: %w
Error message
wgctl: %w
What it means
KernelConfigurer.getPeer could not create a wgctrl client with wgctrl.New(). On Linux and FreeBSD wgctrl opens a netlink socket (falling back to the /dev/wg userspace protocol) to talk to the kernel WireGuard module; construction fails when the module is unavailable or the socket cannot be opened due to permissions. This happens before any device query, so every kernel-mode peer/device operation through getPeer is blocked by it.
Source
Thrown at client/iface/configurer/kernel_unix.go:220
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 {
return wgtypes.Peer{}, fmt.Errorf("get device %s: %w", ifaceName, err)
}
for _, peer := range wgDevice.Peers {
if peer.PublicKey.String() == peerPubKey {
return peer, nil
}
}
return wgtypes.Peer{}, ErrPeerNotFoundView on GitHub (pinned to 93e97f4bf1)
Solutions
- Load the module: sudo modprobe wireguard (and install wireguard-tools/DKMS so it persists)
- Run the daemon as root or with CAP_NET_ADMIN
- If kernel WireGuard cannot be provided, use the userspace configurer (wireguard-go device with NewUSPConfigurer) instead
- Probe wgctrl.New() at startup and log a clear 'kernel WireGuard unavailable' diagnostic
Example fix
// before: assume kernel WireGuard exists
kernelCfg := configurer.NewKernelConfigurer(ifaceName)
// after: probe and fall back to the userspace configurer
if _, err := wgctrl.New(); err != nil {
log.Warnf("kernel WireGuard unavailable (%v), falling back to userspace", err)
// build a wireguard-go device and use configurer.NewUSPConfigurer(dev, ifaceName, recorder)
} Defensive patterns
Strategy: fallback
Validate before calling
// probe kernel WireGuard support once at startup
func kernelWgAvailable() bool {
c, err := wgctrl.New()
if err != nil {
return false
}
defer c.Close()
return true
} Try / catch
wg, err := wgctrl.New()
if err != nil {
log.Warnf("kernel WireGuard unavailable (%v); using userspace device", err)
// construct wireguard-go device + NewUSPConfigurer instead of NewKernelConfigurer
} Prevention
- Ship or load the wireguard kernel module on hosts meant to run kernel mode
- Grant the daemon CAP_NET_ADMIN (containers: --cap-add=NET_ADMIN)
- Probe wgctrl.New() at startup and select kernel vs userspace mode from the result
- Log the probe failure once with a clear remediation hint instead of failing per operation
When it happens
Trigger: Kernel WireGuard module not loaded or not built into the kernel (no CONFIG_WIREGUARD); wireguard-kmod package missing on FreeBSD; process without CAP_NET_ADMIN opening the netlink socket; restrictive container or seccomp profile blocking netlink.
Common situations: Bare-metal or VM host without wireguard installed; minimal container images lacking kernel headers/modules; agent started unprivileged; custom kernels compiled without WireGuard support.
Related errors
- received error "%w" while configuring interface %s with port
- received error "%w" while adding allowed Ip to peer on inter
- get device %s: %w
- create %s interface: %w
- install service: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/207ffaf0722ffe0e.
Report an issue: GitHub.