prometheus/node_exporter · error

getdevs() failed

Error message

getdevs() failed

What it means

In the DragonFly BSD devstat collector (devstat_dragonfly.go), Update calls C._get_ndevs() to count block devices via devstat_getdevs. A return of -1 means the underlying getdevs()/devstat_getdevs call failed, so the collector cannot enumerate disk statistics and returns this error.

Solutions

  1. Ensure the node_exporter user can open /dev/devstat (adjust device permissions or run with adequate privileges)
  2. Verify the kernel has DEVFS/devstat enabled ('devstat' sysctl or kern.devstat available)
  3. Run outside restricted jails/containers, or bind-mount/devfs-rule the devstat device into it
  4. Disable the diskstats/devstat collector on hosts where devstat is unavailable
Defensive patterns

Strategy: validation

Validate before calling

// shell pre-flight: exporter user must reach the devstat device
[ -e /dev/devstat ] && [ -r /dev/devstat ] || echo "devstat unavailable; devstat collector will fail"

Prevention

When it happens

Trigger: C._get_ndevs() == -1 in devstatCollector.Update — the C helper's devstat_getdevs or device-enumeration call returned failure, typically because the devstat device (/dev/devstat) cannot be opened or devstat_checkdevs fails.

Common situations: node_exporter run without permission to open /dev/devstat; running in a jail or container without device access; kernel without devstat support compiled/enabled.

Related errors


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

Appendix: source

Thrown at collector/devstat_dragonfly.go:132

		),
		transfersDesc: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, devstatSubsystem, "transfers_total"),
			"The total number of transactions completed.",
			[]string{"device"}, nil,
		),
		blocksDesc: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, devstatSubsystem, "blocks_total"),
			"The total number of bytes given in terms of the devices blocksize.",
			[]string{"device"}, nil,
		),
		logger: logger,
	}, nil
}

func (c *devstatCollector) Update(ch chan<- prometheus.Metric) error {
	count := C._get_ndevs()
	if count == -1 {
		return errors.New("getdevs() failed")
	}
	if count == -2 {
		return errors.New("calloc() failed")
	}

	for i := C.int(0); i < count; i++ {
		stats := C._get_stats(i)
		device := fmt.Sprintf("%s%d", C.GoString(&stats.device[0]), stats.unit)

		ch <- prometheus.MustNewConstMetric(c.bytesDesc, prometheus.CounterValue, float64(stats.bytes), device)
		ch <- prometheus.MustNewConstMetric(c.transfersDesc, prometheus.CounterValue, float64(stats.transfers), device)
		ch <- prometheus.MustNewConstMetric(c.blocksDesc, prometheus.CounterValue, float64(stats.blocks), device)
	}

	return nil
}

View on GitHub (pinned to 17ddd77c59)