{"record":{"id":"10c803553e05f8fe","repo":"tailscale/tailscale","slug":"get-input-chain-w","errorCode":null,"errorMessage":"get input chain: %w","messagePattern":"get input chain: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/linuxfw/nftables_runner.go","lineNumber":876,"sourceCode":"\t\treturn nil, fmt.Errorf(\"nftables for IPv6 are not available on this host\")\n\t}\n\tif addr.Is6() {\n\t\treturn n.nft6, nil\n\t}\n\treturn n.nft4, nil\n}\n\n// AddLoopbackRule adds an nftables rule to permit loopback traffic to\n// a local Tailscale IP. This rule is added only if it does not already exist.\nfunc (n *nftablesRunner) AddLoopbackRule(addr netip.Addr) error {\n\tnf, err := n.getNFTByAddr(addr)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error setting up nftables for IP family of %v: %w\", addr, err)\n\t}\n\n\tinputChain, err := getChainFromTable(n.conn, nf.Filter, chainNameInput)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get input chain: %w\", err)\n\t}\n\n\tif err := insertLoopbackRule(n.conn, nf.Proto, nf.Filter, inputChain, addr); err != nil {\n\t\treturn fmt.Errorf(\"add loopback rule: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// DelLoopbackRule removes the nftables rule permitting loopback\n// traffic to a Tailscale IP.\nfunc (n *nftablesRunner) DelLoopbackRule(addr netip.Addr) error {\n\tnf, err := n.getNFTByAddr(addr)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error setting up nftables for IP family of %v: %w\", addr, err)\n\t}\n\n\tinputChain, err := getChainFromTable(n.conn, nf.Filter, chainNameInput)","sourceCodeStart":858,"sourceCodeEnd":894,"githubUrl":"https://github.com/tailscale/tailscale/blob/6e0912f97994f927632b34ae9e63b53d6516a6ac/util/linuxfw/nftables_runner.go#L858-L894","documentation":"AddLoopbackRule needs the standard \"input\" chain of the address family's filter table and this error means getChainFromTable couldn't get it. Two distinct causes share this wrap: errorChainNotFound ('chain input not found in table filter') when the base chains were never created — the doc for newNfTablesRunner explicitly says it does NOT guarantee tables/chains exist — or the underlying 'list chains' netlink failure. Callers that skipped base setup hit the first; broken environments the second.","triggerScenarios":"Calling AddLoopbackRule on a runner whose EnsureBase/chain provisioning never ran (chains missing from the filter table), on a host whose filter table or input chain was flushed/deleted by another program, or when the netlink chain listing fails (permissions/kernel support).","commonSituations":"Code using linuxfw.New + AddLoopbackRule without EnsureBase; external tools (nft flush ruleset, docker, firewalld reload) removing the input chain mid-run; unprivileged processes failing at the netlink dump.","solutions":["Call the runner's base setup (EnsureBase) before AddLoopbackRule — it creates the filter table chains this API depends on.","Verify the chain exists: `nft list table ip filter` should show chain input.","If the error chain is the netlink one (wrapped errno), fix capabilities/kernel support as for the 'list chains' error.","Re-run the operation after restoring the table; AddLoopbackRule is idempotent."],"exampleFix":"// before\nerr := fw.AddLoopbackRule(addr) // get input chain: chain input not found in table filter\n\n// after\nif err := fw.EnsureBase(); err != nil { // creates filter table + input chain etc.\n\treturn err\n}\nerr := fw.AddLoopbackRule(addr)","handlingStrategy":"validation","validationCode":"if err := fw.EnsureBase(); err != nil { // creates filter table + input chain\n\treturn err\n}\n// now AddLoopbackRule cannot hit 'chain input not found'","typeGuard":"func isChainNotFound(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"not found in table\")\n}","tryCatchPattern":"err := fw.AddLoopbackRule(addr)\nif isChainNotFound(err) {\n\t// base chains absent: run EnsureBase once and retry\n\tif berr := fw.EnsureBase(); berr != nil {\n\t\treturn berr\n\t}\n\terr = fw.AddLoopbackRule(addr)\n}","preventionTips":["Always call EnsureBase (or the runner's setup path) before loopback-rule APIs on a fresh runner.","Monitor for external tools flushing the filter table while tailscaled runs.","Treat 'not found in table' inside these wraps as an initialization-order signal, not corruption."],"tags":["go","linux","nftables","tailscale","initialization-order","loopback","netfilter"],"backgroundTag":"nftables-chain-not-found","analyzedSha":"6e0912f97994f927632b34ae9e63b53d6516a6ac","analyzedAt":"2026-08-18T08:17:25.280Z","contentChangedAt":"2026-08-18T08:17:25.280Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}