netbirdio/netbird · warning
couldn't find module path for %s, error: %v
Error message
couldn't find module path for %s, error: %v
What it means
tryToLoadModule() failed to determine the on-disk path of the wireguard (or tun) kernel module. getModulePath walks moduleRoot, i.e. /lib/modules/$(uname -r) computed at package init, matching module file names; the wrapped %v is the filesystem error from that walk. Note a module simply absent yields an empty path and returns (false, nil), so this message means walking the module tree itself errored, which is rare because per-entry errors are skipped. WireGuardModuleIsLoaded logs it and returns false, so the agent falls back to userspace wireguard.
Source
Thrown at client/iface/device/kernel_module_linux.go:131
// for the existence of the wireguard module without actually
// creating a link.
//
// As a side-effect, this will also let the kernel lazy-load
// the wireguard module.
link.attrs.MTU = math.MaxInt
err := netlink.LinkAdd(link)
return errors.Is(err, syscall.EINVAL)
}
func tryToLoadModule(moduleName string) (bool, error) {
if isModuleEnabled(moduleName) {
return true, nil
}
modulePath, err := getModulePath(moduleName)
if err != nil {
return false, fmt.Errorf("couldn't find module path for %s, error: %v", moduleName, err)
}
if modulePath == "" {
return false, nil
}
log.Infof("trying to load %s module", moduleName)
err = loadModuleWithDependencies(moduleName, modulePath)
if err != nil {
return false, fmt.Errorf("couldn't load %s module, error: %v", moduleName, err)
}
return true, nil
}
func isModuleEnabled(name string) bool {
builtin, builtinErr := isBuiltinModule(name)
state, statusErr := moduleStatus(name)
return (builtinErr == nil && builtin) || (statusErr == nil && state >= loading)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Verify /lib/modules/$(uname -r) exists, is readable, and matches the running kernel
- Reinstall the matching kernel modules package and run depmod -a
- If kernel WireGuard is unavailable, explicitly accept userspace mode by setting NB_WG_KERNEL_DISABLED=true
- Read the wrapped %v to find the exact fs error and fix that path
Defensive patterns
Strategy: fallback
Validate before calling
// verify the module tree exists and matches the running kernel
root := filepath.Join("/lib/modules", kernelRelease())
if info, err := os.Stat(root); err != nil || !info.IsDir() {
log.Warn("kernel module tree missing; agent will use userspace wireguard")
} Try / catch
if !device.WireGuardModuleIsLoaded() {
// kernel wireguard unavailable (module lookup/load failed);
// proceed in userspace mode instead of failing bring-up
} Prevention
- Install kernel module packages matching the running kernel and run depmod after updates
- Mount /lib/modules fully (or not at all) in containers
- Accept and monitor the userspace fallback path as a deliberate degradation
When it happens
Trigger: Filesystem-level failures while walking /lib/modules/<kernel-release> (permission or I/O errors); partial or broken bind-mounts of the module directory in containers; odd layouts after kernel upgrades.
Common situations: Hardened/minimal systems with restricted /lib/modules, containers with incomplete module trees, module directory left inconsistent by an interrupted kernel package update.
Related errors
- link add: %w
- wgctl: %w
- create %s interface: %w
- failed to list profiles: %w
- failed to get active profile: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/6c753d6265618055.
Report an issue: GitHub.