{"record":{"id":"b18669c584f62140","repo":"prometheus/node_exporter","slug":"failed-to-open-sysfs-w-b18669","errorCode":null,"errorMessage":"failed to open sysfs: %w","messagePattern":"failed to open sysfs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/dmmultipath_linux.go","lineNumber":88,"sourceCode":"\t)\n\tdmmultipathPathState = prometheus.NewDesc(\n\t\tprometheus.BuildFQName(namespace, \"dmmultipath\", \"path_state\"),\n\t\t\"Reports the underlying device state for a multipath path, as read from /sys/block/<dev>/device/state.\",\n\t\t[]string{\"device\", \"path\", \"state\"}, nil,\n\t)\n)\n\ntype dmMultipathCollector struct {\n\tfs     blockdevice.FS\n\tlogger *slog.Logger\n}\n\n// NewDMMultipathCollector returns a new Collector exposing Device Mapper\n// multipath device metrics from /sys/block/dm-*.\nfunc NewDMMultipathCollector(logger *slog.Logger) (Collector, error) {\n\tfs, err := blockdevice.NewFS(*procPath, *sysPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to open sysfs: %w\", err)\n\t}\n\n\treturn &dmMultipathCollector{\n\t\tfs:     fs,\n\t\tlogger: logger,\n\t}, nil\n}\n\nfunc (c *dmMultipathCollector) Update(ch chan<- prometheus.Metric) error {\n\tdevices, err := c.fs.DMMultipathDevices()\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 DM-multipath devices\", \"err\", err)\n\t\t\treturn ErrNoData\n\t\t}\n\t\treturn fmt.Errorf(\"failed to scan DM-multipath devices: %w\", err)\n\t}\n","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/dmmultipath_linux.go#L70-L106","documentation":"NewDMMultipathCollector wraps a failure from blockdevice.NewFS(*procPath, *sysPath) as \"failed to open sysfs\". The block device FS constructor validates both the procfs and sysfs roots; this error indicates one of them could not be used, preventing the dm-multipath collector from being created.","triggerScenarios":"blockdevice.NewFS fails because --path.procfs or --path.sysfs does not exist, is unreadable, or is not a directory. Called from NewDMMultipathCollector during collector registration and from the dm-multipath tests.","commonSituations":"Containerized node_exporter without /sys or /proc mounted; typo'd --path.sysfs/--path.procfs flags; running on non-Linux where the expected mounts are absent despite the build-tag-gated collector being enabled.","solutions":["Verify both --path.procfs (default /proc) and --path.sysfs (default /sys) point to mounted, readable directories","Mount procfs and sysfs into the container: -v /proc:/proc:ro -v /sys:/sys:ro","Correct any typo or override of the path flags","Check that the paths are directories, not regular files or symlinks to nothing"],"exampleFix":"// before\nnode_exporter --path.sysfs=/sysfs-typo\n// after\nnode_exporter --path.sysfs=/sys","handlingStrategy":"validation","validationCode":"for _, p := range []string{procPath, sysPath} {\n    if st, err := os.Stat(p); err != nil || !st.IsDir() {\n        // fix --path.procfs / --path.sysfs before enabling dm-multipath collector\n    }\n}","typeGuard":null,"tryCatchPattern":"c, err := collector.NewDMMultipathCollector(logger)\nif err != nil {\n    return fmt.Errorf(\"dm-multipath collector disabled: %w\", err)\n}","preventionTips":["Mount both /proc and /sys read-only in containers","Keep default path flags unless you have a specific mount layout","Validate paths at service startup with a health check"],"tags":["linux","sysfs","dm-multipath","blockdevice"],"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"}