netbirdio/netbird · error

remove legacy forwarding rule: %v

Error message

remove legacy forwarding rule: %v

What it means

Accumulated by router.RemoveAllLegacyRouteRules when iptablesClient.DeleteIfExists fails for any rule whose key starts with the ForwardingFormat prefix. Unlike the per-rule paths, this sweeps all legacy rules and collects failures in a go-multierror, deleting only the map entries whose kernel delete succeeded. Leftover failures mean permissive '-j ACCEPT' forwarding rules survive.

Source

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

// 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) {
	r.legacyManagement = isLegacy
}

// RemoveAllLegacyRouteRules removes all legacy routing rules for mgmt servers pre route acls
func (r *router) RemoveAllLegacyRouteRules() error {
	var merr *multierror.Error
	for k, rule := range r.rules {
		if !strings.HasPrefix(k, firewall.ForwardingFormatPrefix) {
			continue
		}
		if err := r.iptablesClient.DeleteIfExists(tableFilter, chainRTFWDIN, rule...); err != nil {
			merr = multierror.Append(merr, fmt.Errorf("remove legacy forwarding rule: %v", err))
		} else {
			delete(r.rules, k)
		}
	}

	r.updateState()

	return nberrors.FormatErrorOrNil(merr)
}

func (r *router) Reset() error {
	var merr *multierror.Error
	if err := r.cleanUpDefaultForwardRules(); err != nil {
		merr = multierror.Append(merr, err)
	}

	if err := r.ipsetCounter.Flush(); err != nil {
		merr = multierror.Append(merr, err)

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. After the failure, list leftovers: sudo iptables -S NETBIRD-RT-FWD-IN and delete each ACCEPT rule manually
  2. Retry RemoveAllLegacyRouteRules (idempotent: DeleteIfExists skips absent rules)
  3. Restart the agent and immediately run down/up to resynchronize state
  4. Check the multierror body to see which specific rule specs failed
Defensive patterns

Strategy: fallback

Try / catch

if err := r.RemoveAllLegacyRouteRules(); err != nil {
	// fall back to a manual sweep so no permissive ACCEPT rules survive
	log.Warnf("automatic legacy sweep incomplete: %v; verify NETBIRD-RT-FWD-IN", err)
}

Prevention

When it happens

Trigger: Called when disconnecting from a legacy management or transitioning to route ACLs: iterates r.rules, deletes each legacy forwarding spec from NETBIRD-RT-FWD-IN. Fails per rule on iptables invocation errors (lock, backend, missing chain handled as success by DeleteIfExists only when the rule is absent).

Common situations: netbird down after chains were partially flushed manually; iptables backend changed mid-session; host under heavy parallel firewall churn.

Related errors


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