prometheus/node_exporter · error

couldn't get netstats

Error message

couldn't get netstats: %w

What it means

The netstat collector's Update reads /proc/net/netstat via the procfs library (proc.Netstat()). If the procfs parser fails to read or parse that file, Update returns this wrapped error, which the scrape framework reports as a failed collection of the netstat collector.

Solutions

  1. Verify /proc/net/netstat exists and is readable from inside the exporter's namespace (cat /proc/net/netstat).
  2. Update the prometheus/procfs dependency (and node_exporter) to a version supporting your kernel's netstat format.
  3. Check proc mount permissions/hidepid settings for the exporter user.
  4. Restart the exporter / check for transient procfs read failures; if persistent, run with the same kernel the exporter was built for.

Example fix

// before
netStats, err := c.proc.Netstat()
if err != nil {
	return fmt.Errorf("couldn't get netstats: %w", err)
}
// after (log and continue with degraded output instead of failing the whole scrape)
netStats, err := c.proc.Netstat()
if err != nil {
	c.logger.Warn("failed to read netstat; skipping netstat metrics", "err", err)
	return nil // or handle snmp separately
}
Defensive patterns

Strategy: try-catch

Validate before calling

import "os"
// Pre-check the source file readability before scraping:
if f, err := os.Open(*procPath + "/self/net/netstat"); err != nil {
	// skip netstat collection this scrape
} else {
	f.Close()
}

Type guard

null

Try / catch

// Scrape handler: log collector failure, keep serving other collectors
if err := c.Update(ch); err != nil {
	if errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission) {
		logger.Warn("netstat unavailable in this environment", "err", err)
	} else {
		logger.Error("netstat collection failed", "err", err)
	}
}

Prevention

When it happens

Trigger: c.proc.Netstat() errors when /proc/net/netstat is missing, unreadable, or has an unexpected format the procfs parser rejects (e.g. malformed kernel output or truncated file).

Common situations: Containers with a stripped /proc; kernel versions whose /proc/net/netstat layout isn't understood by the pinned procfs library; permission issues (hidepid).

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at collector/netstat_linux.go:82

	// Network statistics in /proc/net are network namespace local. Reading
	// them via the current process' /proc/self/net keeps the same semantics
	// while allowing the use of the procfs parsers.
	proc, err := fs.Self()
	if err != nil {
		return nil, fmt.Errorf("failed to open /proc/self: %w", err)
	}

	return &netStatCollector{
		proc:         proc,
		fieldPattern: pattern,
		logger:       logger,
	}, nil
}

func (c *netStatCollector) Update(ch chan<- prometheus.Metric) error {
	netStats, err := c.proc.Netstat()
	if err != nil {
		return fmt.Errorf("couldn't get netstats: %w", err)
	}
	snmpStats, err := c.proc.Snmp()
	if err != nil {
		return fmt.Errorf("couldn't get SNMP stats: %w", err)
	}
	snmp6Stats, err := c.proc.Snmp6()
	if err != nil {
		return fmt.Errorf("couldn't get SNMP6 stats: %w", err)
	}

	c.emitStruct(ch, netStats.TcpExt)
	c.emitStruct(ch, netStats.IpExt)
	c.emitStruct(ch, snmpStats.Ip)
	c.emitStruct(ch, snmpStats.Icmp)
	c.emitStruct(ch, snmpStats.IcmpMsg)
	c.emitStruct(ch, snmpStats.Tcp)
	c.emitStruct(ch, snmpStats.Udp)
	c.emitStruct(ch, snmpStats.UdpLite)

View on GitHub (pinned to 17ddd77c59)