prometheus/node_exporter · error

couldn't get tcp6stats

Error message

couldn't get tcp6stats: %w

What it means

After collecting IPv4 stats, Update checks whether /proc/net/tcp6 exists and, if so, collects IPv6 TCP stats via getTCPStats(syscall.AF_INET6), merging them into the totals. A failure in that IPv6 call is wrapped as "couldn't get tcp6stats". The whole scrape fails rather than reporting only IPv4 data.

Solutions

  1. Verify kernel has CONFIG_INET6_DIAG enabled (`ls /proc/net/tcp6` works but `ss -6` fails suggests this)
  2. Grant netlink capabilities in containers as for the IPv4 case
  3. If IPv6 is intentionally unusable, disable tcpstat via --collector.tcpstat or boot with IPv6 fully disabled so /proc/net/tcp6 disappears
  4. Report upstream if the kernel rejects valid inet_diag IPv6 queries
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat("/proc/net/tcp6"); err == nil {
    if _, err := net.Listen("tcp6", ":0"); err != nil {
        // IPv6 present in procfs but not functional — expect tcp6stats failures
    }
}

Try / catch

if err := coll.Update(ch); err != nil {
    if strings.Contains(err.Error(), "tcp6stats") {
        log.Warn("IPv6 tcp stats unavailable", "err", err)
    }
}

Prevention

When it happens

Trigger: /proc/net/tcp6 exists (IPv6 enabled) but the AF_INET6 inet_diag request fails: netlink dial error, kernel rejects the sock_diag query for IPv6, or response parsing fails.

Common situations: IPv6 enabled in /proc but kernel built without CONFIG_INET6_DIAG; container security policies denying IPv6 netlink queries; unusual IPv6-only sockets confusing older kernels.

Related errors


AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07). Data as JSON: /api/errors/0efbadd261bd561c. Report an issue: GitHub.

Appendix: source

Thrown at collector/tcpstat_linux.go:140

	UID     uint32
	Inode   uint32
}

func parseInetDiagMsg(b []byte) *InetDiagMsg {
	return (*InetDiagMsg)(unsafe.Pointer(&b[0]))
}

func (c *tcpStatCollector) Update(ch chan<- prometheus.Metric) error {
	tcpStats, err := getTCPStats(syscall.AF_INET)
	if err != nil {
		return fmt.Errorf("couldn't get tcpstats: %w", err)
	}

	// if enabled ipv6 system
	if _, hasIPv6 := os.Stat(procFilePath("net/tcp6")); hasIPv6 == nil {
		tcp6Stats, err := getTCPStats(syscall.AF_INET6)
		if err != nil {
			return fmt.Errorf("couldn't get tcp6stats: %w", err)
		}

		for st, value := range tcp6Stats {
			tcpStats[st] += value
		}
	}

	for st, value := range tcpStats {
		ch <- c.desc.mustNewConstMetric(value, st.String())
	}

	return nil
}

func getTCPStats(family uint8) (map[tcpConnectionState]float64, error) {
	const TCPFAll = 0xFFF
	const InetDiagInfo = 2
	const SockDiagByFamily = 20

View on GitHub (pinned to 17ddd77c59)