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
- Confirm /sys/fs/btrfs still exists and is populated at scrape time
- Check dmesg for btrfs errors and repair/remount affected filesystems
- Verify permissions for the node_exporter user on the btrfs sysfs files
- 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
- Avoid unmounting btrfs filesystems during scrape windows
- Monitor dmesg for btrfs sysfs read errors
- Keep procfs dependency updated with kernel attribute changes
- Alert only on persistent, not transient, scrape failures
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
- failed to retrieve bcache stats
- failed to retrieve bcachefs stats
- failed to open sysfs
- failed to scan DM-multipath devices
- couldn't get NUMA meminfo
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 nilView on GitHub (pinned to 17ddd77c59)