tailscale/tailscale · error
error listing rules: %v
Error message
error listing rules: %v
What it means
EnsureSNATForDst failed listing existing nat/POSTROUTING rules (table.List) with %v; without the listing it cannot decide which SNAT rules are stale versus present. Causes: iptables execution failure, missing nat table/module, or lost privileges.
Source
Thrown at util/linuxfw/iptables_runner.go:278
return fmt.Errorf("adding %v in v4/filter/ts-forward: %w", args, err)
}
return nil
}
func (i *iptablesRunner) AddDNATRule(origDst, dst netip.Addr) error {
table := i.getIPTByAddr(dst)
return table.Insert("nat", "PREROUTING", 1, "--destination", origDst.String(), "-j", "DNAT", "--to-destination", dst.String())
}
// EnsureSNATForDst sets up firewall to ensure that all traffic aimed for dst, has its source ip set to src:
// - creates a SNAT rule if not already present
// - ensures that any no longer valid SNAT rules for the same dst are removed
func (i *iptablesRunner) EnsureSNATForDst(src, dst netip.Addr) error {
table := i.getIPTByAddr(dst)
rules, err := table.List("nat", "POSTROUTING")
if err != nil {
return fmt.Errorf("error listing rules: %v", err)
}
// iptables accept either address or a CIDR value for the --destination flag, but converts an address to /32
// CIDR. Explicitly passing a /32 CIDR made it possible to test this rule.
dstPrefix, err := dst.Prefix(32)
if err != nil {
return fmt.Errorf("error calculating prefix of dst %v: %v", dst, err)
}
// wantsArgsPrefix is the prefix of the SNAT rule for the provided destination.
// We should only have one POSTROUTING rule with this prefix.
wantsArgsPrefix := fmt.Sprintf("-d %s -j SNAT --to-source", dstPrefix.String())
// wantsArgs is the actual SNAT rule that we want.
wantsArgs := fmt.Sprintf("%s %s", wantsArgsPrefix, src.String())
for _, r := range rules {
args := argsFromPostRoutingRule(r)
if strings.HasPrefix(args, wantsArgsPrefix) {
if strings.HasPrefix(args, wantsArgs) {
return nilView on GitHub (pinned to 6e0912f979)
Solutions
- Verify CAP_NET_ADMIN and that the nat table is available (iptables_nat module)
- Retry listing — transient failures under concurrent netfilter access occur
- Log the raw iptables output captured in the error to pinpoint the failing invocation
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at util/linuxfw/iptables_runner.go:278 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18).
Data as JSON: /api/errors/ca6f000dcd638061.
Report an issue: GitHub.