tailscale/tailscale · error

flushing %s/%s: %w

Error message

flushing %s/%s: %w

What it means

DelBase's del helper: ClearChain (flush) on a table/chain errored with something other than not-exist (which returns nil as desired state). The flush of a Tailscale chain failed — typically permissions or transient ip(6)tables failure during teardown; %s/%s name the table and chain.

Source

Thrown at util/linuxfw/iptables_runner.go:409

		if err := delChain(ipt, "nat", "ts-postrouting"); err != nil {
			return err
		}
	}

	return nil
}

// DelBase empties but does not remove custom Tailscale chains from
// netfilter via iptables.
func (i *iptablesRunner) DelBase() error {
	del := func(ipt iptablesInterface, table, chain string) error {
		if err := ipt.ClearChain(table, chain); err != nil {
			if isNotExistError(err) {
				// nonexistent chain. That's fine, since it's
				// the desired state anyway.
				return nil
			}
			return fmt.Errorf("flushing %s/%s: %w", table, chain, err)
		}
		return nil
	}

	for _, ipt := range i.getTables() {
		if err := del(ipt, "filter", "ts-input"); err != nil {
			return err
		}
		if err := del(ipt, "filter", "ts-forward"); err != nil {
			return err
		}
	}
	for _, ipt := range i.getNATTables() {
		if err := del(ipt, "nat", "ts-postrouting"); err != nil {
			return err
		}
	}

View on GitHub (pinned to 6e0912f979)

Solutions

  1. Retry DelBase — teardown runs while interfaces/rules may still be settling
  2. Verify privileges persist through shutdown (not a torn-down namespace)
  3. Tolerate leftover empty chains if a later cleanup pass runs: not-exist is already treated as success
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at util/linuxfw/iptables_runner.go:409 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/ce7d5b5044ac8485. Report an issue: GitHub.