{"record":{"id":"bffb0e6442fe6ca3","repo":"tailscale/tailscale","slug":"error-syncing-egress-service-configs-w","errorCode":null,"errorMessage":"error syncing egress service configs: %w","messagePattern":"error syncing egress service configs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/containerboot/egressservices.go","lineNumber":182,"sourceCode":"\tep.longSleep = sleepDuration * 10\n}\n\n// sync triggers an egress proxy config resync. The resync calculates the diff between config and status to determine if\n// any firewall rules need to be updated. Currently using status in state Secret as a reference for what is the current\n// firewall configuration is good enough because - the status is keyed by the Pod IP - we crash the Pod on errors such\n// as failed firewall update\nfunc (ep *egressProxy) sync(ctx context.Context, nm netmapState) error {\n\tcfgs, err := ep.getConfigs()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error retrieving egress service configs: %w\", err)\n\t}\n\tstatus, err := ep.getStatus(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error retrieving current egress proxy status: %w\", err)\n\t}\n\tnewStatus, err := ep.syncEgressConfigs(cfgs, status, nm)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error syncing egress service configs: %w\", err)\n\t}\n\tif !servicesStatusIsEqual(newStatus, status) {\n\t\tif err := ep.setStatus(ctx, newStatus, nm); err != nil {\n\t\t\treturn fmt.Errorf(\"error setting egress proxy status: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// addrsHaveChanged returns true if the provided netmap state contains tailnet address change for this proxy node.\nfunc (ep *egressProxy) addrsHaveChanged(nm netmapState) bool {\n\treturn !views.SliceEqual(views.SliceOf(ep.tailnetAddrs), nm.self.Addresses())\n}\n\n// syncEgressConfigs adds and deletes firewall rules to match the desired\n// configuration. It uses the provided status to determine what is currently\n// applied and updates the status after a successful sync.\nfunc (ep *egressProxy) syncEgressConfigs(cfgs egressservices.Configs, status *egressservices.Status, nm netmapState) (*egressservices.Status, error) {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/cmd/containerboot/egressservices.go#L164-L200","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"newStatus, err := ep.syncEgressConfigs(cfgs, status, nm)\nif err != nil {\n\t// match on the inner stage wrappers to classify\n\tmsg := err.Error()\n\tswitch {\n\tcase strings.Contains(msg, \"SNAT\"), strings.Contains(msg, \"adding rules\"):\n\t\t// netfilter/capability problem — check NET_ADMIN\n\tcase strings.Contains(msg, \"tailnet target\"):\n\t\t// config problem — fix annotation\n\t}\n\treturn fmt.Errorf(\"error syncing egress service configs: %w\", err)\n}","preventionTips":["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"],"tags":["kubernetes","firewall","netfilter","go","containerboot"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}