prometheus/node_exporter · error

could not get sysfs device info

Error message

could not get sysfs device info: %w

What it means

For attributes the kernel does not expose over netlink (speed, duplex, MTU details, address info), the netclass collector reads per-device files under /sys/class/net/<dev>/. getSysfsAttributes() returns an error if reading/walking those sysfs directories fails, and Update aborts with 'could not get sysfs device info'.

Solutions

  1. Mount /sys into the container: docker run -v /sys:/sys:ro ... (or equivalent bind mount in Kubernetes hostPath).
  2. Verify ls /sys/class/net works and files like /sys/class/net/eth0/speed are readable by the exporter user.
  3. Re-check whether the error is a race with device removal; if so, a node_exporter upgrade may make per-device sysfs failures non-fatal.
  4. Inspect the wrapped error to see which path/syscall failed; ensure the exporter runs as a user with read access to sysfs.
  5. Confirm the host, not a Docker-in-Docker inner container, owns the /sys being read.

Example fix

// docker run before (sysfs missing -> collector fails)
docker run prom/node-exporter
// after
docker run -v /proc:/host/proc:ro -v /sys:/host/sys:ro --net=host --privileged prom/node-exporter
Defensive patterns

Strategy: validation

Validate before calling

// preflight: sysfs must expose per-device attribute dirs
if _, err := os.Stat("/sys/class/net"); err != nil {
	return fmt.Errorf("sysfs not available: %w", err)
}
entries, _ := os.ReadDir("/sys/class/net")
for _, e := range entries {
	if _, err := os.Stat(filepath.Join("/sys/class/net", e.Name(), "speed")); err != nil {
		// that device's sysfs attrs will be missing
	}
}

Try / catch

if err := collector.Update(ch); err != nil {
	var perr *fs.PathError
	if errors.As(err, &perr) && strings.Contains(err.Error(), "sysfs") {
		logger.Warn("sysfs unreadable; check container mounts", "path", perr.Path)
	}
}

Prevention

When it happens

Trigger: getSysfsAttributes(relevantLinks) returns an error: /sys is not mounted, /sys/class/net/<iface> entries are unreadable (permissions), or an I/O error occurs while reading device attribute files (e.g. device hot-unplugged mid-scan).

Common situations: Containers launched without /sys mounted read-write or read-only (common in minimal Docker configs missing --volume /sys:/sys:ro); host /sys hidden by LSM policies; NICs removed between the rtnetlink dump and the sysfs read (race in virtualized environments).

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/642d22236d89f064. Report an issue: GitHub.

Appendix: source

Thrown at collector/netclass_rtnl_linux.go:77

	}

	// Get most attributes from Netlink
	lMsgs, err := c.getNetClassInfoRTNL()
	if err != nil {
		return fmt.Errorf("could not get net class info: %w", err)
	}

	relevantLinks := make([]rtnetlink.LinkMessage, 0, len(lMsgs))
	for _, msg := range lMsgs {
		if !c.ignoredDevicesPattern.MatchString(msg.Attributes.Name) {
			relevantLinks = append(relevantLinks, msg)
		}
	}

	// Read sysfs for attributes that Netlink doesn't expose
	sysfsAttrs, err := getSysfsAttributes(relevantLinks)
	if err != nil {
		return fmt.Errorf("could not get sysfs device info: %w", err)
	}

	// Parse all the info and update metrics
	for _, msg := range relevantLinks {
		upDesc := prometheus.NewDesc(
			prometheus.BuildFQName(namespace, c.subsystem, "up"),
			"Value is 1 if operstate is 'up', 0 otherwise.",
			[]string{"device"},
			nil,
		)
		upValue := 0.0
		if msg.Attributes.OperationalState == rtnetlink.OperStateUp {
			upValue = 1.0
		}
		ch <- prometheus.MustNewConstMetric(upDesc, prometheus.GaugeValue, upValue, msg.Attributes.Name)

		infoDesc := prometheus.NewDesc(
			prometheus.BuildFQName(namespace, c.subsystem, "info"),

View on GitHub (pinned to 17ddd77c59)