{"record":{"id":"f6baab3a2ee5413e","repo":"netbirdio/netbird","slug":"set-filter-w","errorCode":null,"errorMessage":"set filter: %w","messagePattern":"set filter: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/uspfilter/filter.go","lineNumber":341,"sourceCode":"\t\treturn nil, fmt.Errorf(\"update local IPs: %w\", err)\n\t}\n\tm.fragments = newFragmentTracker(m.logger)\n\n\tif disableConntrack {\n\t\tlog.Info(\"conntrack is disabled\")\n\t} else {\n\t\tm.udpTracker = conntrack.NewUDPTracker(conntrack.DefaultUDPTimeout, m.logger, flowLogger)\n\t\tm.icmpTracker = conntrack.NewICMPTracker(conntrack.DefaultICMPTimeout, m.logger, flowLogger)\n\t\tm.tcpTracker = conntrack.NewTCPTracker(conntrack.DefaultTCPTimeout, m.logger, flowLogger)\n\t}\n\tif m.netstack && m.localForwarding {\n\t\tif err := m.initForwarder(); err != nil {\n\t\t\tlog.Errorf(\"failed to initialize forwarder: %v\", err)\n\t\t}\n\t}\n\tif err := iface.SetFilter(m); err != nil {\n\t\tm.fragments.Close()\n\t\treturn nil, fmt.Errorf(\"set filter: %w\", err)\n\t}\n\treturn m, nil\n}\n\n// blockInvalidRouted installs drop rules for traffic to the wg overlay that\n// arrives via the routing path. v4 and v6 are independent: a v6 install\n// failure leaves v4 protection in place (and vice versa) so the returned\n// slice always contains whatever was successfully installed, even on error.\n// Callers must persist the slice so DisableRouting can clean partial state.\nfunc (m *Manager) blockInvalidRouted(iface common.IFaceMapper) ([]firewall.Rule, error) {\n\twgPrefix := iface.Address().Network\n\tlog.Debugf(\"blocking invalid routed traffic for %s\", wgPrefix)\n\n\tsources := []netip.Prefix{netip.PrefixFrom(netip.IPv4Unspecified(), 0)}\n\tv6Net := iface.Address().IPv6Net\n\tif v6Net.IsValid() {\n\t\tsources = append(sources, netip.PrefixFrom(netip.IPv6Unspecified(), 0))\n\t}","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/uspfilter/filter.go#L323-L359","documentation":"Returned by the uspfilter Manager constructor (client/firewall/uspfilter/filter.go:341) when iface.SetFilter(m) fails. WGIface.SetFilter (client/iface/iface.go:250) errors with 'userspace packet filtering not handled on this device' when tun.FilteredDevice() is nil - i.e. the interface is not a wireguard-go userspace device (kernel WireGuard mode, or a device wrapper without packet filtering). uspfilter filtering only works when packets traverse the in-process device, so the constructor aborts (after closing the fragment tracker).","triggerScenarios":"Building the uspfilter firewall manager while the agent runs in kernel WireGuard mode on Linux (wintun/kernel interfaces expose no FilteredDevice); netstack-less configurations; a tun implementation that does not wire FilteredDevice before SetFilter is called.","commonSituations":"Forcing uspfilter via flags/env on a kernel-mode setup; platform selection code choosing the wrong firewall backend (uspfilter instead of nftables/iptables) in kernel mode; embedded builds where the device wrapper lacks the filter hook.","solutions":["Only construct the uspfilter manager when the interface is a userspace/netstack device; select nftables/iptables or WFP backends in kernel mode","Check wgIface.GetWGDevice() / FilteredDevice() for nil before creating the manager and fall back to the platform's kernel firewall","Initialize the FilteredDevice before the firewall manager in the engine bring-up sequence","On error, prefer failing ACL setup loudly over silently running without filters"],"exampleFix":"// before\nif err := iface.SetFilter(m); err != nil {\n    m.fragments.Close()\n    return nil, fmt.Errorf(\"set filter: %w\", err)\n}\n// after - choose the backend by device capability before constructing\nif iface.GetWGDevice() == nil {\n    return nil, fmt.Errorf(\"uspfilter requires a userspace device\")\n}\nif err := iface.SetFilter(m); err != nil {\n    m.fragments.Close()\n    return nil, fmt.Errorf(\"set filter: %w\", err)\n}","handlingStrategy":"type-guard","validationCode":"if iface.GetWGDevice() == nil {\n    return fmt.Errorf(\"uspfilter requires a userspace device; select the kernel firewall backend instead\")\n}\nfw, err := uspfilter.Create(iface, ...)","typeGuard":"func supportsUserspaceFilter(wg common.IFaceMapper) bool {\n    return wg.GetWGDevice() != nil && wg.FilteredDevice() != nil\n}","tryCatchPattern":"fw, err := uspfilter.Create(iface, ...)\nif err != nil {\n    if strings.Contains(err.Error(), \"set filter\") {\n        fw, err = nftables.Create(iface, ...) // kernel backend fallback\n        if err != nil {\n            return err\n        }\n    } else {\n        return err\n    }\n}","preventionTips":["Select the firewall backend from the interface mode (kernel vs userspace) at engine init","Do not force uspfilter via flags on kernel WireGuard setups","Ensure FilteredDevice is wired before ACL initialization in new tun implementations"],"tags":["uspfilter","firewall","acl","mode-mismatch"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}