netbirdio/netbird · error

remove legacy forwarding rule %s -> %s: %v

Error message

remove legacy forwarding rule %s -> %s: %v

What it means

Returned by router.removeLegacyRouteRule when iptablesClient.DeleteIfExists(tableFilter, NETBIRD-RT-FWD-IN, rule...) fails for a tracked legacy rule. DeleteIfExists tolerates an absent rule, so the error means the iptables invocation itself failed, not that the rule was missing.

Source

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

		return err
	}

	rule := []string{"-s", pair.Source.String(), "-d", pair.Destination.String(), "-j", routingFinalForwardJump}
	if err := r.iptablesClient.Append(tableFilter, chainRTFWDIN, rule...); err != nil {
		return fmt.Errorf("add legacy forwarding rule %s -> %s: %v", pair.Source, pair.Destination, err)
	}

	r.rules[ruleKey] = rule

	return nil
}

func (r *router) removeLegacyRouteRule(pair firewall.RouterPair) error {
	ruleKey := firewall.GenKey(firewall.ForwardingFormat, pair)

	if rule, exists := r.rules[ruleKey]; exists {
		if err := r.iptablesClient.DeleteIfExists(tableFilter, chainRTFWDIN, rule...); err != nil {
			return fmt.Errorf("remove legacy forwarding rule %s -> %s: %v", pair.Source, pair.Destination, err)
		}
		delete(r.rules, ruleKey)

		if err := r.decrementSetCounter(rule); err != nil {
			return fmt.Errorf("decrement ipset counter: %w", err)
		}
	}

	return nil
}

// GetLegacyManagement returns the current legacy management mode
func (r *router) GetLegacyManagement() bool {
	return r.legacyManagement
}

// SetLegacyManagement sets the route manager to use legacy management mode
func (r *router) SetLegacyManagement(isLegacy bool) {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Retry the removal; DeleteIfExists makes it idempotent
  2. Verify with sudo iptables -S NETBIRD-RT-FWD-IN and manually delete leftovers: sudo iptables -D NETBIRD-RT-FWD-IN -s <src> -d <dst> -j ACCEPT
  3. Restart the agent after any iptables backend change
  4. Check /run/xtables.lock holders if failures cluster
Defensive patterns

Strategy: try-catch

Try / catch

if err := r.iptablesClient.DeleteIfExists(tableFilter, chainRTFWDIN, rule...); err != nil {
	if strings.Contains(err.Error(), "does not exist") || strings.Contains(err.Error(), "No chain") {
		return nil // already cleaned; converge
	}
	return fmt.Errorf("remove legacy forwarding rule: %v", err)
}

Prevention

When it happens

Trigger: RemoveNatRule/RemoveAllLegacyRouteRules path on a legacy rule previously stored in r.rules. Fires on xtables lock contention, iptables backend switched legacy/nft after agent start, or the chain deleted out-of-band causing an opaque backend error.

Common situations: Config management flushing NETBIRD chains concurrently; host updated iptables alternatives while the daemon ran; SELinux denying the iptables exec on teardown.

Related errors


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