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

  1. Re-run the removal or Close - the delete is idempotent once the rule is absent
  2. Verify with ip6tables-save -t nat | grep NETBIRD that nothing lingers
  3. 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

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


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/116faa071befda1d. Report an issue: GitHub.