netbirdio/netbird · warning
remove v6 NAT rule: %w
Error message
remove v6 NAT rule: %w
What it means
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.
Source
Thrown at client/firewall/iptables/manager_linux.go:315
defer m.mutex.Unlock()
if pair.Destination.IsPrefix() && pair.Destination.Prefix.Addr().Is6() {
if !m.hasIPv6() {
return nil
}
return m.router6.RemoveNatRule(pair)
}
var merr *multierror.Error
if err := m.router.RemoveNatRule(pair); err != nil {
merr = multierror.Append(merr, fmt.Errorf("remove v4 NAT rule: %w", err))
}
if m.hasIPv6() && pair.Dynamic {
v6Pair := firewall.ToV6NatPair(pair)
if err := m.router6.RemoveNatRule(v6Pair); err != nil {
merr = multierror.Append(merr, fmt.Errorf("remove v6 NAT rule: %w", err))
}
}
return nberrors.FormatErrorOrNil(merr)
}
func (m *Manager) SetLegacyManagement(isLegacy bool) error {
if err := firewall.SetLegacyManagement(m.router, isLegacy); err != nil {
return err
}
if m.hasIPv6() {
return firewall.SetLegacyManagement(m.router6, isLegacy)
}
return nil
}
// Reset firewall to the default state
func (m *Manager) Close(stateManager *statemanager.Manager) error {View on GitHub (pinned to 93e97f4bf1)
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
Defensive patterns
Strategy: retry
Try / catch
err := mgr.RemoveNatRule(pair)
if err != nil {
var merr *multierror.Error
if errors.As(err, &merr) && len(merr.Errors) == 1 && strings.Contains(merr.Errors[0].Error(), "remove v6 NAT rule") {
// only the v6 mirror failed; v4 half is gone. Retry once, then accept.
err = mgr.RemoveNatRule(pair)
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: External ip6tables-restore/firewalld reload removing chains first; repeated teardown of the same pair; v6 module unloaded on the host.
Related errors
- add NAT rule: %w
- add v6 NAT rule: %w
- remove v4 NAT rule: %w
- reset v6 acl manager: %w
- reset v6 router: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/116faa071befda1d.
Report an issue: GitHub.