{"record":{"id":"50d9ba090b8306d2","repo":"prometheus/node_exporter","slug":"failed-to-open-sysfs-w-50d9ba","errorCode":null,"errorMessage":"failed to open sysfs: %w","messagePattern":"failed to open sysfs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/btrfs_linux.go","lineNumber":44,"sourceCode":"\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"github.com/prometheus/procfs/btrfs\"\n)\n\n// A btrfsCollector is a Collector which gathers metrics from Btrfs filesystems.\ntype btrfsCollector struct {\n\tfs     btrfs.FS\n\tlogger *slog.Logger\n}\n\nfunc init() {\n\tregisterCollector(\"btrfs\", defaultEnabled, NewBtrfsCollector)\n}\n\n// NewBtrfsCollector returns a new Collector exposing Btrfs statistics.\nfunc NewBtrfsCollector(logger *slog.Logger) (Collector, error) {\n\tfs, err := btrfs.NewFS(*sysPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to open sysfs: %w\", err)\n\t}\n\n\treturn &btrfsCollector{\n\t\tfs:     fs,\n\t\tlogger: logger,\n\t}, nil\n}\n\n// Update retrieves and exports Btrfs statistics.\n// It implements Collector.\nfunc (c *btrfsCollector) Update(ch chan<- prometheus.Metric) error {\n\tstats, err := c.fs.Stats()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to retrieve Btrfs stats from procfs: %w\", err)\n\t}\n\n\tioctlStatsMap, err := c.getIoctlStats()\n\tif err != nil {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/btrfs_linux.go#L26-L62","documentation":"NewBtrfsCollector wraps errors from btrfs.NewFS(*sysPath) in \"failed to open sysfs\". The sysfs handle needed to read /sys/fs/btrfs statistics could not be created, so the btrfs collector fails to initialize. Like the other collectors, this surfaces at node_exporter startup when the collector is enabled.","triggerScenarios":"Enabling the btrfs collector where /sys is absent/not sysfs, --path.sysfs points to a wrong path, permissions deny access, or on kernels/environments where the btrfs sysfs directory structure is missing.","commonSituations":"Containerized node_exporter without /sys mounted; hosts with CONFIG_BTRFS_FS but no btrfs sysfs exposure; custom test setups passing an invalid sysPath; LSM policy blocking /sys traversal.","solutions":["Ensure /sys is mounted sysfs and readable, and that --path.sysfs is correct","Disable the btrfs collector (--no-collector.btrfs) if no btrfs filesystems are used","Check SELinux/AppArmor audit logs and adjust policy to allow reading /sys/fs/btrfs","Run with host namespaces in Kubernetes (hostPID/mount /sys:ro) when containerized"],"exampleFix":"// before\n collector, err := NewNodeCollector(logger, \"btrfs\")\n// after\n if _, err := os.Stat(filepath.Join(*sysPath, \"fs\", \"btrfs\")); err != nil {\n\tlogger.Info(\"btrfs sysfs missing; not enabling collector\")\n\treturn nil\n }\n collector, err = NewNodeCollector(logger, \"btrfs\")","handlingStrategy":"fallback","validationCode":"if fi, err := os.Stat(filepath.Join(*sysPath, \"fs\", \"btrfs\")); err != nil || !fi.IsDir() { /* skip btrfs collector */ }","typeGuard":"func btrfsSysfsPresent(sysPath string) bool { fi, err := os.Stat(filepath.Join(sysPath, \"fs\", \"btrfs\")); return err == nil && fi.IsDir() }","tryCatchPattern":"c, err := collector.NewNodeCollector(logger)\nif err != nil {\n\tlogger.Warn(\"btrfs collector unavailable\", \"err\", err)\n\tc = nil\n}","preventionTips":["Enable btrfs collector only on hosts using btrfs","Ensure /sys is mounted ro in containers","Validate --path.sysfs at deployment time","Review SELinux/AppArmor policies for /sys/fs/btrfs access"],"tags":["linux","sysfs","collector-init","btrfs"],"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"}