prometheus/node_exporter · error

devstat_getdevs failed

Error message

devstat_getdevs failed

What it means

In the FreeBSD devstat collector (devstat_freebsd.go), Update calls the cgo helper C._get_stats(c.devinfo, &stats), which wraps devstat_getdevs. A return of -1 means the kernel device-statistics query failed, so the collector cannot read any disk metrics and returns this error for the scrape.

Solutions

  1. Grant the exporter's user permission to read /dev/devstat (devfs.rules or group membership)
  2. Restart node_exporter to refresh its cached devinfo after device changes/hot-plug
  3. Confirm devstat is available on the host (kern.devstat sysctl exists) and the process is not jailed without device access
  4. Disable the diskstats collector on hosts where devstat is not usable
Defensive patterns

Strategy: try-catch

Try / catch

if err := c.Update(ch); err != nil {
    if strings.Contains(err.Error(), "devstat_getdevs failed") {
        c.logger.Warn("devstat query failed; refreshing state may help", "err", err)
    }
    return err
}

Prevention

When it happens

Trigger: C._get_stats(c.devinfo, &stats) == -1 in devstatCollector.Update — devstat_getdevs failed, most commonly because /dev/devstat cannot be opened by the exporter process, or devinfo is stale after a device-list change.

Common situations: node_exporter lacking read permission on /dev/devstat; running inside a FreeBSD jail without devstat access; devstat state invalidated after hot-plug device changes.

Related errors


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

Appendix: source

Thrown at collector/devstat_freebsd.go:92

			[]string{"device"}, nil,
		), prometheus.CounterValue},
		blocks: typedDesc{prometheus.NewDesc(
			prometheus.BuildFQName(namespace, devstatSubsystem, "blocks_transferred_total"),
			"The total number of blocks transferred.",
			[]string{"device"}, nil,
		), prometheus.CounterValue},
		logger: logger,
	}, nil
}

func (c *devstatCollector) Update(ch chan<- prometheus.Metric) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	var stats *C.Stats
	n := C._get_stats(c.devinfo, &stats)
	if n == -1 {
		return errors.New("devstat_getdevs failed")
	}

	base := unsafe.Pointer(stats)
	for i := C.int(0); i < n; i++ {
		offset := i * C.int(C.sizeof_Stats)
		stat := (*C.Stats)(unsafe.Pointer(uintptr(base) + uintptr(offset)))

		device := fmt.Sprintf("%s%d", C.GoString(&stat.device[0]), stat.unit)
		ch <- c.bytes.mustNewConstMetric(float64(stat.bytes.read), device, "read")
		ch <- c.bytes.mustNewConstMetric(float64(stat.bytes.write), device, "write")
		ch <- c.transfers.mustNewConstMetric(float64(stat.transfers.other), device, "other")
		ch <- c.transfers.mustNewConstMetric(float64(stat.transfers.read), device, "read")
		ch <- c.transfers.mustNewConstMetric(float64(stat.transfers.write), device, "write")
		ch <- c.duration.mustNewConstMetric(float64(stat.duration.other), device, "other")
		ch <- c.duration.mustNewConstMetric(float64(stat.duration.read), device, "read")
		ch <- c.duration.mustNewConstMetric(float64(stat.duration.write), device, "write")
		ch <- c.busyTime.mustNewConstMetric(float64(stat.busyTime), device)
		ch <- c.blocks.mustNewConstMetric(float64(stat.blocks), device)

View on GitHub (pinned to 17ddd77c59)