{"record":{"id":"dadc74c6611ef579","repo":"netbirdio/netbird","slug":"apply-network-d-w","errorCode":null,"errorMessage":"apply network -d: %w","messagePattern":"apply network -d: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/router_linux.go","lineNumber":693,"sourceCode":"\t\tmarkValue = nbnet.PreroutingFwmarkMasqueradeReturn\n\t}\n\n\trule := []string{\"-i\", r.wgIface.Name()}\n\tif pair.Inverse {\n\t\trule = []string{\"!\", \"-i\", r.wgIface.Name()}\n\t}\n\n\trule = append(rule,\n\t\t\"-m\", \"conntrack\",\n\t\t\"--ctstate\", \"NEW\",\n\t)\n\tsourceExp, err := r.applyNetwork(\"-s\", pair.Source, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"apply network -s: %w\", err)\n\t}\n\tdestExp, err := r.applyNetwork(\"-d\", pair.Destination, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"apply network -d: %w\", err)\n\t}\n\n\trule = append(rule, sourceExp...)\n\trule = append(rule, destExp...)\n\trule = append(rule,\n\t\t\"-j\", \"MARK\", \"--set-mark\", fmt.Sprintf(\"%#x\", markValue),\n\t)\n\n\t// Ensure nat rules come first, so the mark can be overwritten.\n\t// Currently overwritten by the dst-type LOCAL rules for redirected traffic.\n\tif err := r.iptablesClient.Insert(tableMangle, chainRTPRE, 1, rule...); err != nil {\n\t\t// TODO: rollback ipset counter\n\t\treturn fmt.Errorf(\"error while adding marking rule for %s: %v\", pair.Destination, err)\n\t}\n\n\tr.rules[ruleKey] = rule\n\n\tr.updateState()","sourceCodeStart":675,"sourceCodeEnd":711,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/router_linux.go#L675-L711","documentation":"Destination-side twin of the source error in addNatRule(): applyNetwork(\"-d\", pair.Destination, nil) fails while creating/refcounting an ipset for a destination network set. With plain prefixes this path cannot error, so seeing this message always implies a set-based destination route and an ipset subsystem failure, wrapped as 'apply network -d'.","triggerScenarios":"pair.Destination.IsSet() true and ipsetCounter.Increment failing: ipset modules missing, CAP_NET_ADMIN absent, hashed set name too long for the kernel, or concurrent set creation racing (duplicate-create netlink error not treated as benign). Sources with a plain prefix succeed, isolating the failure to destination sets.","commonSituations":"Management applies routes whose destination is a network set (e.g. 'all peers' groups) to hosts without ipset support; hardened containers with seccomp blocking NETLINK_NETFILTER; older kernels with stricter ipset name/type validation; one-off breakage after ipset packages were updated on the host.","solutions":["Confirm the failing side is the destination set from the log context, then `modprobe ip_set ip_set_hash_net`","Test manually: `sudo ipset create test hash:net` (and destroy it after)","Grant CAP_NET_ADMIN / relax seccomp for the agent container so netlink ipset calls work","Check the set name length in the preceding 'create or get ipset' log line; report over-length names as a management/agent bug","Retry the route application once modules and permissions are fixed"],"exampleFix":"// before: destination and source failures are indistinguishable in ops output\ndestExp, err := r.applyNetwork(\"-d\", pair.Destination, nil)\nif err != nil {\n    return fmt.Errorf(\"apply network -d: %w\", err)\n}\n\n// after: carry the set name into the error for direct diagnosis\ndestExp, err := r.applyNetwork(\"-d\", pair.Destination, nil)\nif err != nil {\n    if pair.Destination.IsSet() {\n        return fmt.Errorf(\"apply destination set %s: %w\", pair.Destination.Set.HashedName(), err)\n    }\n    return fmt.Errorf(\"apply network -d: %w\", err)\n}","handlingStrategy":"validation","validationCode":"func setApplicable(net firewall.Network) error {\n    if !net.IsSet() {\n        return nil\n    }\n    if _, err := os.Stat(\"/proc/net/ip_set\"); err != nil {\n        return fmt.Errorf(\"ipset unavailable for set-based networks: %w\", err)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"Same as the source variant: wrap the pair add, distinguish set failures (ipset subsystem) from prefix failures (cannot happen), and requeue the route for the next reconciliation cycle.","preventionTips":["Prefer prefix-based destinations when the host kernel lacks ipset","Smoke-test `ipset create` in host/container bring-up","Alert on 'apply network -d' lines; they always indicate set-based routing issues"],"tags":["network","linux","ipset","iptables","routing"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}