{"record":{"id":"139ec901c08d17c5","repo":"netbirdio/netbird","slug":"add-route-filtering-w","errorCode":null,"errorMessage":"add route filtering: %w","messagePattern":"add route filtering: %w","errorType":"exception","errorClass":"firewall.ErrIPv6NotInitialized","httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/manager_linux.go","lineNumber":216,"sourceCode":"\t\treturn nil, fmt.Errorf(\"add peer filtering for %s: %w\", ip, firewall.ErrIPv6NotInitialized)\n\t}\n\treturn m.aclMgr6.AddPeerFiltering(id, ip, proto, sPort, dPort, action, ipsetName)\n}\n\nfunc (m *Manager) AddRouteFiltering(\n\tid []byte,\n\tsources []netip.Prefix,\n\tdestination firewall.Network,\n\tproto firewall.Protocol,\n\tsPort, dPort *firewall.Port,\n\taction firewall.Action,\n) (firewall.Rule, error) {\n\tm.mutex.Lock()\n\tdefer m.mutex.Unlock()\n\n\tif isIPv6RouteRule(sources, destination) {\n\t\tif !m.hasIPv6() {\n\t\t\treturn nil, fmt.Errorf(\"add route filtering: %w\", firewall.ErrIPv6NotInitialized)\n\t\t}\n\t\treturn m.router6.AddRouteFiltering(id, sources, destination, proto, sPort, dPort, action)\n\t}\n\n\treturn m.router.AddRouteFiltering(id, sources, destination, proto, sPort, dPort, action)\n}\n\nfunc isIPv6RouteRule(sources []netip.Prefix, destination firewall.Network) bool {\n\tif destination.IsPrefix() {\n\t\treturn destination.Prefix.Addr().Is6()\n\t}\n\treturn len(sources) > 0 && sources[0].Addr().Is6()\n}\n\n// DeletePeerRule from the firewall by rule definition\nfunc (m *Manager) DeletePeerRule(rule firewall.Rule) error {\n\tm.mutex.Lock()\n\tdefer m.mutex.Unlock()","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/manager_linux.go#L198-L234","documentation":"AddRouteFiltering classified the rule as IPv6 via isIPv6RouteRule - the destination is a v6 prefix, or destination is not a prefix and the first source prefix is v6 - but the manager has no v6 half. Wraps the sentinel firewall.ErrIPv6NotInitialized, meaning the v6 capability decision (HasIPv6 at Create time) does not match the traffic being programmed.","triggerScenarios":"Calling AddRouteFiltering with destination.Prefix.Addr().Is6() true, or with the first entry of sources being a v6 prefix, while the local overlay address lacks IPv6.","commonSituations":"Management distributes an IPv6 network route (v6 resource range, or a v6 exit node) to a peer whose WgAddr is v4-only; network routes regenerated after the agent connected without v6.","solutions":["Assign the peer a v6 address and restart the agent so the v6 router exists","Scope the v6 route's distribution groups in management so v4-only peers do not receive it","In custom route managers, drop v6 route rules when !wgIface.Address().HasIPv6() instead of forwarding them to the firewall"],"exampleFix":"// before\nrule, err := mgr.AddRouteFiltering(id, sources, dest, proto, sPort, dPort, action)\nif err != nil {\n\treturn err // v6 route on v4-only manager fails the apply\n}\n\n// after\nif isV6 := (dest.IsPrefix() && dest.Prefix.Addr().Is6()) || (!dest.IsPrefix() && len(sources) > 0 && sources[0].Addr().Is6()); isV6 && !wgIface.Address().HasIPv6() {\n\tlog.Debugf(\"skipping v6 route rule: no v6 overlay\")\n\tcontinue\n}\nrule, err := mgr.AddRouteFiltering(id, sources, dest, proto, sPort, dPort, action)","handlingStrategy":"validation","validationCode":"func isV6RouteRule(sources []netip.Prefix, destination firewall.Network) bool {\n    if destination.IsPrefix() {\n        return destination.Prefix.Addr().Is6()\n    }\n    return len(sources) > 0 && sources[0].Addr().Is6()\n}\n\n// before applying route rules:\nif isV6RouteRule(sources, destination) && !wgIface.Address().HasIPv6() {\n    log.Debugf(\"skipping v6 route rule: no v6 firewall\")\n    continue\n}","typeGuard":null,"tryCatchPattern":"rule, err := mgr.AddRouteFiltering(id, sources, destination, proto, sPort, dPort, action)\nif err != nil {\n    if errors.Is(err, firewall.ErrIPv6NotInitialized) {\n        continue // v6 route on a v4-only overlay: skip, keep applying the rest\n    }\n    return err\n}","preventionTips":["Classify rule family (mirror isIPv6RouteRule) before calling the firewall","Re-check HasIPv6() after interface address changes, not only at startup","Scope v6 network routes in management to v6-capable peer groups"],"tags":["iptables","ipv6","firewall","routing","netbird","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}