{"record":{"id":"e5b09fe1d1ebe8f8","repo":"tailscale/tailscale","slug":"checking-for-v-in-s-s-w","errorCode":null,"errorMessage":"checking for %v in %s/%s: %w","messagePattern":"checking for (.+?) in (.+?)/(.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/linuxfw/iptables_runner.go","lineNumber":149,"sourceCode":"\tif i.HasIPV6NAT() {\n\t\treturn i.getTables()\n\t}\n\treturn []iptablesInterface{i.ipt4}\n}\n\n// AddHooks inserts calls to tailscale's netfilter chains in\n// the relevant main netfilter chains. The tailscale chains must\n// already exist. If they do not, an error is returned.\nfunc (i *iptablesRunner) AddHooks() error {\n\t// divert inserts a jump to the tailscale chain in the given table/chain.\n\t// If the jump already exists, it is a no-op.\n\tdivert := func(ipt iptablesInterface, table, chain string) error {\n\t\ttsChain := tsChain(chain)\n\n\t\targs := []string{\"-j\", tsChain}\n\t\texists, err := ipt.Exists(table, chain, args...)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"checking for %v in %s/%s: %w\", args, table, chain, err)\n\t\t}\n\t\tif exists {\n\t\t\treturn nil\n\t\t}\n\t\tif err := ipt.Insert(table, chain, 1, args...); err != nil {\n\t\t\treturn fmt.Errorf(\"adding %v in %s/%s: %w\", args, table, chain, err)\n\t\t}\n\t\treturn nil\n\t}\n\n\tfor _, ipt := range i.getTables() {\n\t\tif err := divert(ipt, \"filter\", \"INPUT\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := divert(ipt, \"filter\", \"FORWARD\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/tailscale/tailscale/blob/6e0912f97994f927632b34ae9e63b53d6516a6ac/util/linuxfw/iptables_runner.go#L131-L167","documentation":"Inside AddHooks' divert closure, the Exists probe for the '-j ts-<chain>' jump in the parent table/chain failed — the iptables query errored (permissions, binary, missing table). The %v/%s/%s name the jump target, table, and chain. Idempotency depends on this check: a jump already present is a no-op, so failure here blocks both detection and insertion.","triggerScenarios":"Thrown at util/linuxfw/iptables_runner.go:149 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure privileges and iptables availability before hook installation","Run AddChains first so the ts- chains the jumps target exist","Retry AddHooks after fixing the environment; it is idempotent when probes succeed"],"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"}