{"record":{"id":"cbcf8937f0c3ca61","repo":"prometheus/node_exporter","slug":"failed-to-open-sysfs-w-cbcf89","errorCode":null,"errorMessage":"failed to open sysfs: %w","messagePattern":"failed to open sysfs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/nvmesubsystem_linux.go","lineNumber":105,"sourceCode":"\t)\n\tnvmesubsystemPathState = prometheus.NewDesc(\n\t\tprometheus.BuildFQName(namespace, \"nvmesubsystem\", \"path_state\"),\n\t\t\"Current NVMe controller path state (1 for the current state, 0 for all others).\",\n\t\t[]string{\"subsystem\", \"controller\", \"transport\", \"state\"}, nil,\n\t)\n)\n\ntype nvmeSubsystemCollector struct {\n\tfs     sysfs.FS\n\tlogger *slog.Logger\n}\n\n// NewNVMeSubsystemCollector returns a new Collector exposing NVMe-oF subsystem\n// path health from /sys/class/nvme-subsystem/.\nfunc NewNVMeSubsystemCollector(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\n\treturn &nvmeSubsystemCollector{\n\t\tfs:     fs,\n\t\tlogger: logger,\n\t}, nil\n}\n\nfunc (c *nvmeSubsystemCollector) Update(ch chan<- prometheus.Metric) error {\n\tsubsystems, err := c.fs.NVMeSubsystemClass()\n\tif err != nil {\n\t\tif errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission) {\n\t\t\tc.logger.Debug(\"Could not read NVMe subsystem info\", \"err\", err)\n\t\t\treturn ErrNoData\n\t\t}\n\t\treturn fmt.Errorf(\"failed to scan NVMe subsystems: %w\", err)\n\t}\n","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/nvmesubsystem_linux.go#L87-L123","documentation":"NewNVMeSubsystemCollector constructs a collector that reads NVMe-oF subsystem health from /sys/class/nvme-subsystem/ via the sysfs package. It calls sysfs.NewFS(*sysPath), where sysPath is the --path.sysfs flag, and wraps any failure in \"failed to open sysfs\". NewFS fails when the given path does not exist or is not usable as a filesystem root, so the collector cannot be constructed.","triggerScenarios":"NewNVMeSubsystemCollector returns this when sysfs.NewFS(*sysPath) fails: --path.sysfs points to a nonexistent path, or the path exists but statfs/mount checks fail (e.g. /sys not mounted, as in containers without sysfs, or a test fixture path that is missing).","commonSituations":"Running node_exporter in a minimal container or chroot without /sys mounted; passing a wrong --path.sysfs value; unit tests using newTestNVMeSubsystemCollector with a fixture directory that was not unpacked (make test unpacks collector/fixtures/sys.ttar); unrelated collector code reused on non-Linux.","solutions":["Mount or verify sysfs exists at the configured path (default /sys): check `ls /sys/class/nvme-subsystem` and mount -t sysfs sysfs /sys if missing","Fix the --path.sysfs flag to point at a real sysfs root","For tests, run `make test` (or unpack collector/fixtures/sys.ttar) so the sysfs fixtures exist","Confirm NVMe-oF subsystems are present; note an empty /sys/class/nvme-subsystem is not this error (missing dir at Update time maps to ErrNoData instead)"],"exampleFix":"// before\nnode_exporter --path.sysfs=/host/sys   # path missing in container\n// after\nnode_exporter --path.sysfs=/sys        # or bind-mount host sysfs: -v /sys:/host/sys:ro","handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(*sysPath); err != nil { return fmt.Errorf(\"sysfs path %q missing: %w\", *sysPath, err) }","typeGuard":"func sysfsAvailable(path string) bool { st, err := os.Stat(path); return err == nil && st.IsDir() }","tryCatchPattern":"c, err := collector.NewNVMeSubsystemCollector(logger)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to open sysfs\") {\n        logger.Warn(\"sysfs unavailable, NVMe metrics disabled\", \"err\", err)\n        return nil // degrade gracefully\n    }\n    return err\n}","preventionTips":["Verify /sys is mounted before starting node_exporter in containers","Always pass a valid --path.sysfs; never point it at an empty placeholder dir","Unpack test fixtures (make test) before running collector unit tests","Bind-mount host /sys read-only when running in Docker/Kubernetes"],"tags":["linux","sysfs","nvme","collector-init"],"backgroundTag":"file-open-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"}