netbirdio/netbird · error
add legacy forwarding rule %s -> %s: %v
Error message
add legacy forwarding rule %s -> %s: %v
What it means
Returned by router.addLegacyRouteRule when iptablesClient.Append(tableFilter, NETBIRD-RT-FWD-IN, '-s <src> -d <dst> -j ACCEPT') fails while installing the permissive legacy rule for pre-route-ACL management. Formatted with %v (not %w), so the cause is embedded as text and is not unwrappable by callers. The rule allows all traffic from pair.Source to pair.Destination, which is why the warning above it matters.
Source
Thrown at client/firewall/iptables/router_linux.go:322
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
}
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)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Ensure NETBIRD-RT-FWD-IN exists (sudo iptables -S NETBIRD-RT-FWD-IN); restart agent to re-init if missing
- Check the log for the earlier createContainers/init failure and fix root cause first
- Upgrade management so the peer leaves legacy mode and uses route ACLs instead
- Confirm root/CAP_NET_ADMIN for the agent process
Example fix
// before (router_linux.go:322): cause not wrappable
return fmt.Errorf("add legacy forwarding rule %s -> %s: %v", pair.Source, pair.Destination, err)
// after
return fmt.Errorf("add legacy forwarding rule %s -> %s: %w", pair.Source, pair.Destination, err) Defensive patterns
Strategy: validation
Validate before calling
if ok, _ := r.iptablesClient.ChainExists(tableFilter, chainRTFWDIN); !ok {
return fmt.Errorf("chain %s missing; run init first", chainRTFWDIN)
} Prevention
- Fix createContainers failures before any AddNatRule in legacy mode
- Upgrade management to leave legacy mode
- Note the %v format: match on message text if you must detect it
When it happens
Trigger: AddNatRule with legacyManagement on, after a successful removeLegacyRouteRule. Append fails when NETBIRD-RT-FWD-IN does not exist (init/createContainers failed or chains were flushed), CAP_NET_ADMIN is missing, or the iptables invocation errors.
Common situations: Old management version plus a host where custom chains were removed manually or by a crashed run; containers where capabilities were dropped after start; nft backend mismatch producing 'No chain/target/match by that name'.
Related errors
- add legacy routing rule: %w
- remove legacy routing rule: %w
- remove legacy forwarding rule %s -> %s: %v
- remove legacy forwarding rule: %v
- add IP to ipset: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/24c085b4155f6955.
Report an issue: GitHub.