netbirdio/netbird · warning

remove v4 NAT rule: %w

Error message

remove v4 NAT rule: %w

What it means

Best-effort teardown error: RemoveNatRule failed to delete the v4 half of a NAT pair via router.RemoveNatRule, and it was accumulated into a multierror (the v6 half is still attempted afterwards). Most commonly the underlying iptables Delete fails because the rule is already gone - chains were flushed externally or a previous Close removed them.

Source

Thrown at client/firewall/iptables/manager_linux.go:309

	return nil
}

func (m *Manager) RemoveNatRule(pair firewall.RouterPair) error {
	m.mutex.Lock()
	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)

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Treat as idempotent cleanup: re-run RemoveNatRule or the full Close to converge
  2. Inspect with iptables-save -t nat | grep NETBIRD to confirm no leftovers remain
  3. If errors persist across restarts, capture the wrapped ip6tables/iptables message from the daemon log and address that layer
Defensive patterns

Strategy: retry

Try / catch

if err := mgr.RemoveNatRule(pair); err != nil {
    var merr *multierror.Error
    if errors.As(err, &merr) {
        for _, e := range merr.Errors {
            log.Debugf("nat teardown partial: %v", e) // usually 'already gone'
        }
        return nil // treat idempotent-teardown noise as success
    }
    return err
}

Prevention

When it happens

Trigger: RemoveNatRule(pair) on a v4-destination pair when the NETBIRD nat chains or the specific rule no longer exist, or the iptables Delete call otherwise errors; result is a *multierror.Error containing 'remove v4 NAT rule: ...'.

Common situations: Agent shutdown racing an external firewall rewrite; double teardown (Close called after a crash-recovery cleanup already removed rules); unprivileged close.

Related errors


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