{"record":{"id":"116faa071befda1d","repo":"netbirdio/netbird","slug":"remove-v6-nat-rule-w","errorCode":null,"errorMessage":"remove v6 NAT rule: %w","messagePattern":"remove v6 NAT rule: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/firewall/iptables/manager_linux.go","lineNumber":315,"sourceCode":"\tdefer m.mutex.Unlock()\n\n\tif pair.Destination.IsPrefix() && pair.Destination.Prefix.Addr().Is6() {\n\t\tif !m.hasIPv6() {\n\t\t\treturn nil\n\t\t}\n\t\treturn m.router6.RemoveNatRule(pair)\n\t}\n\n\tvar merr *multierror.Error\n\n\tif err := m.router.RemoveNatRule(pair); err != nil {\n\t\tmerr = multierror.Append(merr, fmt.Errorf(\"remove v4 NAT rule: %w\", err))\n\t}\n\n\tif m.hasIPv6() && pair.Dynamic {\n\t\tv6Pair := firewall.ToV6NatPair(pair)\n\t\tif err := m.router6.RemoveNatRule(v6Pair); err != nil {\n\t\t\tmerr = multierror.Append(merr, fmt.Errorf(\"remove v6 NAT rule: %w\", err))\n\t\t}\n\t}\n\n\treturn nberrors.FormatErrorOrNil(merr)\n}\n\nfunc (m *Manager) SetLegacyManagement(isLegacy bool) error {\n\tif err := firewall.SetLegacyManagement(m.router, isLegacy); err != nil {\n\t\treturn err\n\t}\n\tif m.hasIPv6() {\n\t\treturn firewall.SetLegacyManagement(m.router6, isLegacy)\n\t}\n\treturn nil\n}\n\n// Reset firewall to the default state\nfunc (m *Manager) Close(stateManager *statemanager.Manager) error {","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/manager_linux.go#L297-L333","documentation":"Teardown counterpart of the dynamic NAT mirror: RemoveNatRule already attempted (and possibly succeeded on) the v4 half, then the v6 mirror removal via router6.RemoveNatRule failed and was accumulated into the multierror. The two halves are attempted independently so a v4 failure does not skip v6 cleanup and vice versa.","triggerScenarios":"RemoveNatRule(pair) with pair.Dynamic true and hasIPv6() true, where the v6 rule Delete fails - e.g. the v6 NETBIRD-RT-NAT chain was already flushed or ip6tables errored.","commonSituations":"External ip6tables-restore/firewalld reload removing chains first; repeated teardown of the same pair; v6 module unloaded on the host.","solutions":["Re-run the removal or Close - the delete is idempotent once the rule is absent","Verify with ip6tables-save -t nat | grep NETBIRD that nothing lingers","Restart + clean stop of the agent lets ShutdownState.Cleanup remove leftovers on the next start"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := mgr.RemoveNatRule(pair)\nif err != nil {\n    var merr *multierror.Error\n    if errors.As(err, &merr) && len(merr.Errors) == 1 && strings.Contains(merr.Errors[0].Error(), \"remove v6 NAT rule\") {\n        // only the v6 mirror failed; v4 half is gone. Retry once, then accept.\n        err = mgr.RemoveNatRule(pair)\n    }\n}","preventionTips":["Remember the v6 mirror exists for every dynamic pair; remove failures are usually already-gone deletes","Keep shutdown sequences serialized so external flushes do not race teardown","Use ip6tables-save to verify convergence after repeated failures"],"tags":["iptables","ipv6","firewall","nat","cleanup","netbird","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}