prometheus/node_exporter · error

failed to retrieve Btrfs stats from procfs

Error message

failed to retrieve Btrfs stats from procfs: %w

What it means

btrfsCollector.Update wraps errors from c.fs.Stats() (the sysfs-based Btrfs statistics read) in "failed to retrieve Btrfs stats from procfs". The message is slightly misleading — it reads from sysfs via the btrfs fs package — but it signals that the statistics walk over /sys/fs/btrfs failed during a scrape. The whole btrfs scrape aborts for that cycle; ioctl-based device stats failures are only logged at debug level and do not cause this error.

Solutions

  1. Confirm /sys/fs/btrfs still exists and is populated at scrape time
  2. Check dmesg for btrfs errors and repair/remount affected filesystems
  3. Verify permissions for the node_exporter user on the btrfs sysfs files
  4. Ignore ioctl device-stat debug messages — they are non-fatal by design

Example fix

// before
 if err := ch-scrape; err != nil { panic(err) }
// after
 if err := scrape(); err != nil {
	if strings.Contains(err.Error(), "failed to retrieve Btrfs stats") {
		logger.Warn("btrfs stats unavailable this cycle", "err", err)
		return
	}
	panic(err)
 }
Defensive patterns

Strategy: retry

Validate before calling

if _, err := os.Stat("/sys/fs/btrfs"); err != nil { /* skip scrape cycle */ }

Try / catch

err := collector.Update(ch)
if err != nil {
	logger.Warn("btrfs stats scrape failed; retrying next interval", "err", err)
	return nil
}

Prevention

When it happens

Trigger: A scrape where /sys/fs/btrfs files could not be read (filesystem unmounted mid-scrape, permission revoked, sysfs read returning EIO), or a kernel change altering expected attribute paths.

Common situations: Unmounting or degraded btrfs arrays during scraping; container environments where sysfs visibility changed after startup; custom kernels lacking expected btrfs sysfs attributes.

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/8ff7bf351a283ed7. Report an issue: GitHub.

Appendix: source

Thrown at collector/btrfs_linux.go:58

// NewBtrfsCollector returns a new Collector exposing Btrfs statistics.
func NewBtrfsCollector(logger *slog.Logger) (Collector, error) {
	fs, err := btrfs.NewFS(*sysPath)
	if err != nil {
		return nil, fmt.Errorf("failed to open sysfs: %w", err)
	}

	return &btrfsCollector{
		fs:     fs,
		logger: logger,
	}, nil
}

// Update retrieves and exports Btrfs statistics.
// It implements Collector.
func (c *btrfsCollector) Update(ch chan<- prometheus.Metric) error {
	stats, err := c.fs.Stats()
	if err != nil {
		return fmt.Errorf("failed to retrieve Btrfs stats from procfs: %w", err)
	}

	ioctlStatsMap, err := c.getIoctlStats()
	if err != nil {
		c.logger.Debug(
			"Error querying btrfs device stats with ioctl",
			"err", err)
		ioctlStatsMap = make(map[string]*btrfsIoctlFsStats)
	}

	for _, s := range stats {
		// match up procfs and ioctl info by filesystem UUID (without dashes)
		var fsUUID = strings.ReplaceAll(s.UUID, "-", "")
		ioctlStats := ioctlStatsMap[fsUUID]
		c.updateBtrfsStats(ch, s, ioctlStats)
	}

	return nil

View on GitHub (pinned to 17ddd77c59)