netbirdio/netbird · error

remove nat rule: %w

Error message

remove nat rule: %w

What it means

Returned by router.RemoveNatRule when removeNatRule(pair) fails. It looks up the rule spec stored under GenKey(NatFormat, pair) and calls DeleteIfExists on the NETBIRD-RT-PRE mangle chain, then decrements the ipset refcounter. The wrap fires on the DeleteIfExists error; failure aborts before updateState, leaving the in-memory map consistent but the rule possibly still in the chain.

Source

Thrown at client/firewall/iptables/router_linux.go:295

	if err := r.addNatRule(pair); err != nil {
		return fmt.Errorf("add nat rule: %w", err)
	}

	if err := r.addNatRule(firewall.GetInversePair(pair)); err != nil {
		return fmt.Errorf("add inverse nat rule: %w", err)
	}

	r.updateState()

	return nil
}

// RemoveNatRule removes an iptables rule pair from forwarding and nat chains
func (r *router) RemoveNatRule(pair firewall.RouterPair) error {
	if pair.Masquerade {
		if err := r.removeNatRule(pair); err != nil {
			return fmt.Errorf("remove nat rule: %w", err)
		}

		if err := r.removeNatRule(firewall.GetInversePair(pair)); err != nil {
			return fmt.Errorf("remove inverse nat rule: %w", err)
		}
	}

	if err := r.removeLegacyRouteRule(pair); err != nil {
		return fmt.Errorf("remove legacy routing rule: %w", err)
	}

	r.updateState()

	return nil
}

// addLegacyRouteRule adds a legacy routing rule for mgmt servers pre route acls
func (r *router) addLegacyRouteRule(pair firewall.RouterPair) error {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Retry removal after a short delay (lock contention is transient)
  2. Verify leftover marks: sudo iptables -t mangle -S NETBIRD-RT-PRE and delete stragglers manually if needed
  3. Keep one iptables backend; restart the agent after switching legacy/nft
  4. Re-run 'sudo netbird down' to drive full teardown
Defensive patterns

Strategy: retry

Try / catch

if err := r.removeNatRule(pair); err != nil {
	// DeleteIfExists is idempotent; transient lock errors clear on retry
	return fmt.Errorf("remove nat rule: %w", err)
}

Prevention

When it happens

Trigger: Removing a masqueraded route/exit-node pair (netbird down, route update, management push). DeleteIfExists rarely fails: xtables lock contention, iptables binary swapped between legacy/nft backends mid-run, or security modules denying exec.

Common situations: Host where iptables was switched from legacy to nft backend (update-alternatives) after agent start; heavy parallel iptables activity by config management (puppet/ansible firewall modules).

Related errors


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