prometheus/node_exporter · error
error obtaining NVMe class info
Error message
error obtaining NVMe class info: %w
What it means
The NVMe collector's Update calls c.fs.NVMeClass() to enumerate /sys/class/nvme devices and read their stats via the sysfs library. When the call fails for a reason other than os.ErrNotExist (the expected 'no NVMe devices' case, handled as ErrNoData), the error is wrapped in this message. It means sysfs is readable but the NVMe class data could not be listed or parsed.
Solutions
- Read the wrapped cause (%w) to determine permission vs parse vs I/O failure.
- Confirm exporter read access: 'ls -la /sys/class/nvme' as the exporter user.
- Retry/observe: transient errors during device hotplug usually clear on the next scrape; treat persistent ones as real failures.
- On parse failures with newer kernels, upgrade node_exporter/procfs sysfs package.
- On hosts without NVMe, expect ErrNoData debug logs instead of this error.
Example fix
// before: masked /sys/class in container causes listing errors // after: mount host sysfs fully read-only // docker run -v /sys:/host/sys:ro node-exporter \ // --path.sysfs=/host/sys --collector.nvme
Defensive patterns
Strategy: try-catch
Validate before calling
// Go: precheck NVMe class directory accessibility
if ents, err := os.ReadDir(filepath.Join(*sysPath, "class/nvme")); err != nil {
log.Printf("nvme class not readable: %v", err)
} else if len(ents) == 0 {
log.Printf("no NVMe devices; collector will no-op")
} Try / catch
// skip no-device case, wrap real errors
if errors.Is(err, os.ErrNotExist) {
return ErrNoData
}
return fmt.Errorf("error obtaining NVMe class info: %w", err) // alert on persistence Prevention
- Enable --collector.nvme only on hosts with NVMe hardware.
- Keep /sys/class/nvme readable by the exporter user (watch container path masking).
- Expect transient errors during device hotplug; alert only on persistent scrape failures.
- Upgrade node_exporter/procfs if kernel sysfs attributes change format.
When it happens
Trigger: c.fs.NVMeClass() returns a non-ErrNotExist error: permission problems under /sys/class/nvme, partially removed NVMe devices changing state mid-read, or unexpected sysfs attribute content the sysfs library cannot parse.
Common situations: Hosts with hot-plugged/failing NVMe drives where device directories vanish between listing and reading; hardened containers that expose /sys but mask subpaths; kernel versions with attribute layouts newer than the bundled sysfs library supports.
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 get vulnerabilities
- failed to open sysfs
- failed to open sysfs
- failed to open sysfs
- failed to scan NVMe subsystems
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/deee515ed4e238e0.
Report an issue: GitHub.
Appendix: source
Thrown at collector/nvme_linux.go:94
func NewNVMeCollector(logger *slog.Logger) (Collector, error) {
fs, err := sysfs.NewFS(*sysPath)
if err != nil {
return nil, fmt.Errorf("failed to open sysfs: %w", err)
}
return &nvmeCollector{
fs: fs,
logger: logger,
}, nil
}
func (c *nvmeCollector) Update(ch chan<- prometheus.Metric) error {
devices, err := c.fs.NVMeClass()
if err != nil {
if errors.Is(err, os.ErrNotExist) {
c.logger.Debug("nvme statistics not found, skipping")
return ErrNoData
}
return fmt.Errorf("error obtaining NVMe class info: %w", err)
}
for _, device := range devices {
// Export device-level metrics
ch <- prometheus.MustNewConstMetric(
nvmeInfo,
prometheus.GaugeValue,
1.0,
device.Name,
device.FirmwareRevision,
device.Model,
device.Serial,
device.State,
device.ControllerID,
)
// Export namespace-level metrics
for _, namespace := range device.Namespaces {View on GitHub (pinned to 17ddd77c59)