{"record":{"id":"deee515ed4e238e0","repo":"prometheus/node_exporter","slug":"error-obtaining-nvme-class-info-w","errorCode":null,"errorMessage":"error obtaining NVMe class info: %w","messagePattern":"error obtaining NVMe class info: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/nvme_linux.go","lineNumber":94,"sourceCode":"func NewNVMeCollector(logger *slog.Logger) (Collector, error) {\n\tfs, err := sysfs.NewFS(*sysPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to open sysfs: %w\", err)\n\t}\n\treturn &nvmeCollector{\n\t\tfs:     fs,\n\t\tlogger: logger,\n\t}, nil\n}\n\nfunc (c *nvmeCollector) Update(ch chan<- prometheus.Metric) error {\n\tdevices, err := c.fs.NVMeClass()\n\tif err != nil {\n\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\tc.logger.Debug(\"nvme statistics not found, skipping\")\n\t\t\treturn ErrNoData\n\t\t}\n\t\treturn fmt.Errorf(\"error obtaining NVMe class info: %w\", err)\n\t}\n\n\tfor _, device := range devices {\n\t\t// Export device-level metrics\n\t\tch <- prometheus.MustNewConstMetric(\n\t\t\tnvmeInfo,\n\t\t\tprometheus.GaugeValue,\n\t\t\t1.0,\n\t\t\tdevice.Name,\n\t\t\tdevice.FirmwareRevision,\n\t\t\tdevice.Model,\n\t\t\tdevice.Serial,\n\t\t\tdevice.State,\n\t\t\tdevice.ControllerID,\n\t\t)\n\n\t\t// Export namespace-level metrics\n\t\tfor _, namespace := range device.Namespaces {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/nvme_linux.go#L76-L112","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: masked /sys/class in container causes listing errors\n// after: mount host sysfs fully read-only\n//   docker run -v /sys:/host/sys:ro node-exporter \\\n//     --path.sysfs=/host/sys --collector.nvme","handlingStrategy":"try-catch","validationCode":"// Go: precheck NVMe class directory accessibility\nif ents, err := os.ReadDir(filepath.Join(*sysPath, \"class/nvme\")); err != nil {\n    log.Printf(\"nvme class not readable: %v\", err)\n} else if len(ents) == 0 {\n    log.Printf(\"no NVMe devices; collector will no-op\")\n}","typeGuard":null,"tryCatchPattern":"// skip no-device case, wrap real errors\nif errors.Is(err, os.ErrNotExist) {\n    return ErrNoData\n}\nreturn fmt.Errorf(\"error obtaining NVMe class info: %w\", err) // alert on persistence","preventionTips":["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."],"tags":["linux","sysfs","nvme","collector"],"backgroundTag":"file-read-failed","analyzedSha":"17ddd77c59ba27e1508e9f7894b1e55b44d6aed3","analyzedAt":"2026-09-07T17:54:06.211Z","contentChangedAt":"2026-09-07T17:54:06.211Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}