{"record":{"id":"190b7d01446542e4","repo":"netbirdio/netbird","slug":"block-wg-v6-net-w","errorCode":null,"errorMessage":"block wg v6 net: %w","messagePattern":"block wg v6 net: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/uspfilter/filter.go","lineNumber":388,"sourceCode":"\t)\n\tif err != nil {\n\t\treturn rules, fmt.Errorf(\"block wg v4 net: %w\", err)\n\t}\n\trules = append(rules, v4Rule)\n\n\tif v6Net.IsValid() {\n\t\tlog.Debugf(\"blocking invalid routed traffic for %s\", v6Net)\n\t\tv6Rule, err := m.addRouteFiltering(\n\t\t\tnil,\n\t\t\tsources,\n\t\t\tfirewall.Network{Prefix: v6Net},\n\t\t\tfirewall.ProtocolALL,\n\t\t\tnil,\n\t\t\tnil,\n\t\t\tfirewall.ActionDrop,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn rules, fmt.Errorf(\"block wg v6 net: %w\", err)\n\t\t}\n\t\trules = append(rules, v6Rule)\n\t}\n\n\t// TODO: Block networks that we're a client of\n\n\treturn rules, nil\n}\n\nfunc (m *Manager) determineRouting() error {\n\tvar disableUspRouting, forceUserspaceRouter bool\n\tvar err error\n\tif val := os.Getenv(EnvDisableUserspaceRouting); val != \"\" {\n\t\tdisableUspRouting, err = strconv.ParseBool(val)\n\t\tif err != nil {\n\t\t\tlog.Warnf(\"failed to parse %s: %v\", EnvDisableUserspaceRouting, err)\n\t\t}\n\t}","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/uspfilter/filter.go#L370-L406","documentation":"Returned by blockInvalidRouted (client/firewall/uspfilter/filter.go:388) when the same drop rule cannot be installed for the IPv6 overlay prefix (v6Net.IsValid() was true, so the agent attempted the v6 leg). Per the function's contract, a v6 failure leaves the v4 rule installed and the returned slice still contains v4 - callers must persist it so DisableRouting can clean partial state. Failures are input-class: an interface-reported v6 prefix that is present but malformed (wrong bit length, non-canonical), or invalid v6 sources.","triggerScenarios":"Dual-stack overlay where iface.Address().IPv6Net reports a valid-but-unusable prefix (e.g. Bits() > 64 or host bits set non-canonically); v6 sources from the network map that fail validation mid-install.","commonSituations":"Management pushes an IPv6 range with an unusual prefix length; agent version mismatch in v6 address normalization (Unmap missing, v4-mapped entries in the v6 net); hosts with flapping v6 capability re-enabling the v6 leg mid-session.","solutions":["Normalize the v6 prefix (Masked(), sane Bits bounds) before calling blockInvalidRouted; skip the v6 leg when normalization deems it unusable","Treat v6 block failure as non-fatal per the IPv6-soft-feature policy: keep v4 protection, log a warning, and continue routing","Always persist the returned partial rules slice so DisableRouting cleans whatever was installed","If v6 is not needed, run the overlay IPv4-only so v6Net.IsValid() is false and the leg is skipped"],"exampleFix":"// before\nv6Rule, err := m.addRouteFiltering(nil, sources, firewall.Network{Prefix: v6Net}, firewall.ProtocolALL, nil, nil, firewall.ActionDrop)\nif err != nil {\n    return rules, fmt.Errorf(\"block wg v6 net: %w\", err)\n}\n// after - keep v4 protection, degrade the v6 leg to a warning\nv6Rule, err := m.addRouteFiltering(nil, sources, firewall.Network{Prefix: v6Net}, firewall.ProtocolALL, nil, nil, firewall.ActionDrop)\nif err != nil {\n    log.Warnf(\"skip invalid routed v6 block for %s: %v\", v6Net, err)\n    return rules, nil\n}\nrules = append(rules, v6Rule)","handlingStrategy":"fallback","validationCode":"v6 := iface.Address().IPv6Net\nif v6.IsValid() && (v6.Bits() < 0 || v6.Bits() > 128 || !v6.Addr().Is6() || v6.Addr().Is4In6()) {\n    // treat as 'no v6' rather than failing EnableRouting\n    v6 = netip.Prefix{}\n}","typeGuard":"func usableOverlayV6(p netip.Prefix) bool {\n    return p.IsValid() && p.Addr().Is6() && !p.Addr().Is4In6() && p.Bits() >= 0 && p.Bits() <= 128\n}","tryCatchPattern":"if err := fw.EnableRouting(); err != nil {\n    if strings.Contains(err.Error(), \"block wg v6 net\") {\n        log.Warnf(\"continuing v4-only routing; v6 default-drop failed: %v\", err)\n        err = nil\n    }\n    if err != nil {\n        return err\n    }\n}","preventionTips":["Apply Unmap()/Masked() to v6 overlay prefixes when parsing management config","Never let a v6 leg failure abort v4 routing - IPv6 is a soft feature","Persist whatever rules were installed so DisableRouting cleans partial state"],"tags":["uspfilter","routing","ipv6","firewall"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}