tailscale/tailscale · error
deleting connmark rule in mangle/OUTPUT: %w
Error message
deleting connmark rule in mangle/OUTPUT: %w
What it means
The second step of iptablesRunner.DelConnmarkSaveRule (util/linuxfw/iptables_runner.go:632): deleting the OUTPUT rule that saved marks on NEW connections (conntrack --ctstate NEW, mark ! 0x0/0xff00, CONNMARK --save-mark). As with the PREROUTING delete, a 'rule does not exist' outcome is silently accepted, so this error means the iptables -t mangle -D OUTPUT call failed for a real reason such as missing CAP_NET_ADMIN, unavailable connmark support, or an iptables binary/backend problem. It surfaces during firewall teardown on both the IPv4 and IPv6 tables (the loop over getTables).
Source
Thrown at util/linuxfw/iptables_runner.go:632
return fmt.Errorf("deleting connmark rule in mangle/PREROUTING: %w", err)
}
// Rule doesn't exist - this is fine for idempotency
}
// Delete OUTPUT rule
args = []string{
"-m", "conntrack",
"--ctstate", "NEW",
"-m", "mark",
"!", "--mark", "0x0/" + fwmarkMask,
"-j", "CONNMARK",
"--save-mark",
"--nfmask", fwmarkMask,
"--ctmask", fwmarkMask,
}
if err := ipt.Delete("mangle", "OUTPUT", args...); err != nil {
if !isNotExistError(err) {
return fmt.Errorf("deleting connmark rule in mangle/OUTPUT: %w", err)
}
// Rule doesn't exist - this is fine for idempotency
}
}
return nil
}
// buildMagicsockPortRule generates the string slice containing the arguments
// to describe a rule accepting traffic on a particular port to iptables. It is
// separated out here to avoid repetition in AddMagicsockPortRule and
// RemoveMagicsockPortRule, since it is important that the same rule is passed
// to Append() and Delete().
func buildMagicsockPortRule(port uint16) []string {
return []string{"-p", "udp", "--dport", strconv.FormatUint(uint64(port), 10), "-j", "ACCEPT"}
}
// AddMagicsockPortRule adds a rule to iptables to allow incoming traffic on
// the specified UDP port, so magicsock can accept incoming connections.View on GitHub (pinned to 6e0912f979)
Solutions
- Run with root/CAP_NET_ADMIN so mangle/OUTPUT is writable
- Check the rule manually: iptables-save -t mangle | grep save-mark, then delete the exact rule by hand
- modprobe xt_connmark xt_conntrack if matches are missing
- Treat as best-effort during shutdown and log it; the rule set is rebuilt on next start
Example fix
// before
if err := ipt.DelConnmarkSaveRule(); err != nil {
return err
}
// after
if err := ipt.DelConnmarkSaveRule(); err != nil {
logf("mangle/OUTPUT connmark cleanup failed: %v", err)
// continue shutdown; stale rules are replaced on next AddConnmarkSaveRule
} Defensive patterns
Strategy: try-catch
Validate before calling
func mangleWritable(ipt *iptables.IPTables) bool {
return ipt.Probe() == nil // iptables binary reachable and responsive
} Try / catch
if err := ipt.DelConnmarkSaveRule(); err != nil {
logf("mangle/OUTPUT connmark cleanup: %v", err)
// continue shutdown; do not abort the process over stale marks
} Prevention
- Grant CAP_NET_ADMIN before any firewall teardown runs
- Never mix versions between the process that adds and the one that deletes rules
- Load xt_connmark/xt_conntrack on minimal hosts at boot
- Log cleanup errors with the full wrapped chain for diagnosis
When it happens
Trigger: DelConnmarkSaveRule invoked when the process cannot modify mangle/OUTPUT: no CAP_NET_ADMIN, missing xt_connmark/xt_conntrack modules, iptables binary missing, or rule text mismatch after a version upgrade (the Add and Del paths must build byte-identical args).
Common situations: Daemon shutdown inside an unprivileged container; downgrade/upgrade of tailscaled where fwmarkMask or rule construction changed; systems where another firewall tool rewrote or flushed chains mid-teardown.
Related errors
- deleting connmark rule in mangle/PREROUTING: %w
- adding %v in filter/ts-input: %w
- failed extracting the new tailscale binary from %q: %w
- mkdir %q: %w
- creating state directory: %w
AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18).
Data as JSON: /api/errors/3a3fb656f03e3dfc.
Report an issue: GitHub.