netbirdio/netbird · error
insert established rule: %w
Error message
insert established rule: %w
What it means
Returned by router.createContainers when insertEstablishedRule(NETBIRD-RT-FWD-OUT) fails: identical INSERT of the conntrack established rule into the outbound filter chain. The message is byte-for-byte the same as error 557's wrap ('insert established rule'), so logs alone do not say which chain failed; the chain must be inferred from ordering (it is the second call, after FWD-IN succeeded).
Source
Thrown at client/firewall/iptables/router_linux.go:463
{chainRTFWDOUT, tableFilter},
{chainRTPRE, tableMangle},
{chainRTNAT, tableNat},
{chainRTRDR, tableNat},
{chainRTMSSCLAMP, tableMangle},
} {
// Fallback: clear chains that survived an unclean shutdown.
if ok, _ := r.iptablesClient.ChainExists(chainInfo.table, chainInfo.chain); ok {
if err := r.iptablesClient.ClearAndDeleteChain(chainInfo.table, chainInfo.chain); err != nil {
log.Warnf("clear stale chain %s in %s: %v", chainInfo.chain, chainInfo.table, err)
}
}
if err := r.iptablesClient.NewChain(chainInfo.table, chainInfo.chain); err != nil {
return fmt.Errorf("create chain %s in table %s: %w", chainInfo.chain, chainInfo.table, err)
}
}
if err := r.insertEstablishedRule(chainRTFWDIN); err != nil {
return fmt.Errorf("insert established rule: %w", err)
}
if err := r.insertEstablishedRule(chainRTFWDOUT); err != nil {
return fmt.Errorf("insert established rule: %w", err)
}
if err := r.addPostroutingRules(); err != nil {
return fmt.Errorf("add static nat rules: %w", err)
}
if err := r.addJumpRules(); err != nil {
return fmt.Errorf("add jump rules: %w", err)
}
if err := r.addMSSClampingRules(); err != nil {
log.Errorf("failed to add MSS clamping rules: %s", err)
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Apply the 557 fixes (module, single instance, lock)
- Distinguish the failing chain by position: the error after 'insert established rule' during init is FWD-OUT when FWD-IN already succeeded
- Verify both chains: sudo iptables -S NETBIRD-RT-FWD-IN; sudo iptables -S NETBIRD-RT-FWD-OUT
- Restart the agent; init recreates and repopulates both chains
Example fix
// before (router_linux.go:463-468): identical messages hide the chain
if err := r.insertEstablishedRule(chainRTFWDIN); err != nil {
return fmt.Errorf("insert established rule: %w", err)
}
if err := r.insertEstablishedRule(chainRTFWDOUT); err != nil {
return fmt.Errorf("insert established rule: %w", err)
}
// after
if err := r.insertEstablishedRule(chainRTFWDIN); err != nil {
return fmt.Errorf("insert established rule into %s: %w", chainRTFWDIN, err)
}
if err := r.insertEstablishedRule(chainRTFWDOUT); err != nil {
return fmt.Errorf("insert established rule into %s: %w", chainRTFWDOUT, err)
} Defensive patterns
Strategy: validation
Validate before calling
# verify the second chain explicitly since the error text is ambiguous sudo iptables -S NETBIRD-RT-FWD-OUT
Try / catch
if err := r.insertEstablishedRule(chainRTFWDOUT); err != nil {
// include the chain in context when wrapping; message alone is ambiguous
return fmt.Errorf("insert established rule into %s: %w", chainRTFWDOUT, err)
} Prevention
- Include the target chain in wrapped error context
- Same preflight as FWD-IN: xt_conntrack must be present
- Check both FWD chains after init failures to locate the real one
When it happens
Trigger: createContainers proceeding past the FWD-IN insert and failing on FWD-OUT: same causes, i.e. missing xt_conntrack, chain removed between creation and insert, or xtables lock contention hitting the second statement.
Common situations: Same environments as 557; intermittent lock contention that only catches the later insert; note the failure leaves FWD-IN populated with no rollback of earlier chains (createContainers returns the error up to init).
Related errors
- create chain %s in table %s: %w
- add IP to ipset: %w
- failed to check rule: %w
- rule already exists
- failed to delete rule: %s, %v: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/950d0a2b7b82dd77.
Report an issue: GitHub.