{"record":{"id":"f7e12e9c2f2a1f26","repo":"tailscale/tailscale","slug":"add-cgnat-rules-w","errorCode":null,"errorMessage":"add cgnat rules: %w","messagePattern":"add cgnat rules: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"wgengine/router/osrouter/router_linux.go","lineNumber":897,"sourceCode":"\t}\n\n\tfor cidr := range r.addrs {\n\t\tif err := r.addLoopbackRule(cidr.Addr()); err != nil {\n\t\t\treturn fmt.Errorf(\"error adding loopback rule: %w\", err)\n\t\t}\n\t}\n\n\t// Re-add the CGNAT rules if we had any set.\n\t// This does not call [linuxRouter.setCGNATDropModeLocked] because that\n\t// function assumes that [linuxRouter.cgnatMode] accurately represents the\n\t// current state in the firewall. This would not be true when we hit this\n\t// code path, and is what we're fixing up here.\n\tif r.cgnatMode != \"\" {\n\t\tif err := r.nfr.AddExternalCGNATRules(r.cgnatMode, r.tunname); err != nil {\n\t\t\t// We currently have no rules set, so change the state to reflect that\n\t\t\t// so we might try again on a future Router update.\n\t\t\tr.cgnatMode = \"\"\n\t\t\treturn fmt.Errorf(\"add cgnat rules: %w\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// getV6FilteringAvailable returns true if the router is able to setup the\n// required tailscale filter rules for IPv6.\nfunc (r *linuxRouter) getV6FilteringAvailable() bool {\n\tif r.nfr == nil {\n\t\treturn false\n\t}\n\treturn r.nfr.HasIPV6() && r.nfr.HasIPV6Filter()\n}\n\n// getV6Available reports whether the router can manage IPv6. r.nfr can be nil if\n// setupNetfilterLocked failed earlier in Set (which continues on error), so\n// treat a nil runner as no IPv6 rather than dereferencing it.","sourceCodeStart":879,"sourceCodeEnd":915,"githubUrl":"https://github.com/tailscale/tailscale/blob/6e0912f97994f927632b34ae9e63b53d6516a6ac/wgengine/router/osrouter/router_linux.go#L879-L915","documentation":"During netfilter mode reprocessing, setNetfilterModeLocked failed to re-add the previously-configured CGNAT external rules (AddExternalCGNATRules). On failure the code resets cgnatMode so a later pass reinstalls them.","triggerScenarios":"Thrown at wgengine/router/osrouter/router_linux.go:897 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Inspect the wrapped netfilter error","Retry the netfilter mode switch / router Set so CGNAT rules are reinstalled","Check for external interference with the Tailscale chains"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"6e0912f97994f927632b34ae9e63b53d6516a6ac","analyzedAt":"2026-08-18T08:17:25.280Z","contentChangedAt":"2026-08-18T08:17:25.280Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}