tailscale/tailscale · error
error syncing egress service configs: %w
Error message
error syncing egress service configs: %w
What it means
Middle wrapper in egressProxy.sync around syncEgressConfigs, the function that computes and applies the netfilter diff (delete removed services, resolve targets, add/update rules, SNAT, MSS clamping). Any failure inside that pipeline — wrapped %w — surfaces here, with the specific stage named by an inner wrapper such as 'error setting up SNAT rule' or 'error adding rules'.
Source
Thrown at cmd/containerboot/egressservices.go:182
ep.longSleep = sleepDuration * 10
}
// sync triggers an egress proxy config resync. The resync calculates the diff between config and status to determine if
// any firewall rules need to be updated. Currently using status in state Secret as a reference for what is the current
// firewall configuration is good enough because - the status is keyed by the Pod IP - we crash the Pod on errors such
// as failed firewall update
func (ep *egressProxy) sync(ctx context.Context, nm netmapState) error {
cfgs, err := ep.getConfigs()
if err != nil {
return fmt.Errorf("error retrieving egress service configs: %w", err)
}
status, err := ep.getStatus(ctx)
if err != nil {
return fmt.Errorf("error retrieving current egress proxy status: %w", err)
}
newStatus, err := ep.syncEgressConfigs(cfgs, status, nm)
if err != nil {
return fmt.Errorf("error syncing egress service configs: %w", err)
}
if !servicesStatusIsEqual(newStatus, status) {
if err := ep.setStatus(ctx, newStatus, nm); err != nil {
return fmt.Errorf("error setting egress proxy status: %w", err)
}
}
return nil
}
// addrsHaveChanged returns true if the provided netmap state contains tailnet address change for this proxy node.
func (ep *egressProxy) addrsHaveChanged(nm netmapState) bool {
return !views.SliceEqual(views.SliceOf(ep.tailnetAddrs), nm.self.Addresses())
}
// syncEgressConfigs adds and deletes firewall rules to match the desired
// configuration. It uses the provided status to determine what is currently
// applied and updates the status after a successful sync.
func (ep *egressProxy) syncEgressConfigs(cfgs egressservices.Configs, status *egressservices.Status, nm netmapState) (*egressservices.Status, error) {View on GitHub (pinned to cfe32b8be6)
Solutions
- Look at the innermost wrapped message — it names the exact netfilter stage that failed
- Ensure the proxy container grants NET_ADMIN (and runs with adequate privileges for iptables/nft)
- Check for iptables/xtables lock contention on the node (other agents, kube-proxy) and retry after they settle
- Align the containerboot firewall mode (iptables vs nftables) with what the host kernel supports
Defensive patterns
Strategy: try-catch
Try / catch
newStatus, err := ep.syncEgressConfigs(cfgs, status, nm)
if err != nil {
// match on the inner stage wrappers to classify
msg := err.Error()
switch {
case strings.Contains(msg, "SNAT"), strings.Contains(msg, "adding rules"):
// netfilter/capability problem — check NET_ADMIN
case strings.Contains(msg, "tailnet target"):
// config problem — fix annotation
}
return fmt.Errorf("error syncing egress service configs: %w", err)
} Prevention
- Always run egress proxy containers with NET_ADMIN capability
- Match containerboot's firewall mode (iptables vs nftables) to the host kernel before deploying
- Watch node-level iptables lock contention when co-locating firewall-manipulating agents
When it happens
Trigger: netfilter operations failing: EnsureSNATForDst or ClampMSSToPMTU denied (missing NET_ADMIN), ensureRulesAdded/ensureRulesDeleted failing on iptables/nft errors (table lock, backend mismatch), or target resolution errors from tailnetTargetIPsForSvc.
Common situations: Container securityContext missing capabilities: ["NET_ADMIN"]; iptables lock contention with kube-proxy or other DaemonSets on a busy node; host firewall switched to a backend the chosen firewall mode does not support.
Related errors
- error deleting services: %w
- error syncing egress service config: %w
- no valid local IP: %v
- failed to add fsnotify watch: %w
- error retrieving egress service configs: %w
AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15).
Data as JSON: /api/errors/bffb0e6442fe6ca3.
Report an issue: GitHub.