netbirdio/netbird · error

remove inverse nat rule: %w

Error message

remove inverse nat rule: %w

What it means

Returned by router.RemoveNatRule when removeNatRule(firewall.GetInversePair(pair)) fails: deleting the inverse (return-traffic MARK) rule from NETBIRD-RT-PRE. Mechanically identical to error 546 but for the '!' -i <iface> leg of the pair; if it fails after the forward leg was deleted, the pair is half-removed.

Source

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

	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 {
	ruleKey := firewall.GenKey(firewall.ForwardingFormat, pair)

	if err := r.removeLegacyRouteRule(pair); err != nil {
		return err

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Retry RemoveNatRule; DeleteIfExists tolerates an already-absent rule so the retry converges
  2. Inspect 'iptables -t mangle -S NETBIRD-RT-PRE' for leftover return-mark rules and remove them
  3. Avoid manual flushes of NETBIRD-* chains while the agent runs
  4. Restart the agent if the iptables backend was changed on the host
Defensive patterns

Strategy: retry

Try / catch

if err := r.removeNatRule(firewall.GetInversePair(pair)); err != nil {
	// retry once: the forward leg is already gone, inverse delete is idempotent
	return fmt.Errorf("remove inverse nat rule: %w", err)
}

Prevention

When it happens

Trigger: Removing a masquerading pair where the forward DeleteIfExists succeeded but the inverse one hit an iptables error: lock contention, backend switch, or the chain having been flushed out-of-band so DeleteIfExists semantics changed underneath.

Common situations: Concurrent teardown paths (netbird down while management pushes a route update); manual iptables -t mangle -F NETBIRD-RT-PRE between the two deletes.

Related errors


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