{"record":{"id":"e4e7bd2533e9278e","repo":"prometheus/node_exporter","slug":"failed-to-open-sysfs-w-e4e7bd","errorCode":null,"errorMessage":"failed to open sysfs: %w","messagePattern":"failed to open sysfs: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/sysctl_linux.go","lineNumber":47,"sourceCode":"\tsysctlIncludeInfo = kingpin.Flag(\"collector.sysctl.include-info\", \"Select sysctl metrics to include as info metrics\").Strings()\n\n\tsysctlInfoDesc = prometheus.NewDesc(prometheus.BuildFQName(namespace, \"sysctl\", \"info\"), \"sysctl info\", []string{\"name\", \"value\", \"index\"}, nil)\n)\n\ntype sysctlCollector struct {\n\tfs      procfs.FS\n\tlogger  *slog.Logger\n\tsysctls []*sysctl\n}\n\nfunc init() {\n\tregisterCollector(\"sysctl\", defaultDisabled, NewSysctlCollector)\n}\n\nfunc NewSysctlCollector(logger *slog.Logger) (Collector, error) {\n\tfs, err := procfs.NewFS(*procPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to open sysfs: %w\", err)\n\t}\n\tc := &sysctlCollector{\n\t\tlogger:  logger,\n\t\tfs:      fs,\n\t\tsysctls: []*sysctl{},\n\t}\n\n\tfor _, include := range *sysctlInclude {\n\t\tsysctl, err := newSysctl(include, true)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tc.sysctls = append(c.sysctls, sysctl)\n\t}\n\n\tfor _, include := range *sysctlIncludeInfo {\n\t\tsysctl, err := newSysctl(include, false)\n\t\tif err != nil {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/sysctl_linux.go#L29-L65","documentation":"NewSysctlCollector wraps procfs.NewFS(*procPath); when opening the /proc (sysctl) filesystem fails, the constructor returns this wrapped error and the sysctl collector is not registered. It almost always means the configured --path.procfs root does not exist or is unreadable. The collector is disabled by default, so it only fires when explicitly enabled with a bad path.","triggerScenarios":"Starting node_exporter with --collector.sysctl enabled while --path.procfs points to a missing, unmounted, or unreadable directory (e.g. wrong container mount, typo like /host/proc when only /proc exists).","commonSituations":"Running node_exporter in a container without /proc bind-mounted to the host path; typo in --path.procfs flag; procfs not mounted in minimal/chroot environments.","solutions":["Fix --path.procfs to point at a valid procfs mount (usually /proc)","Mount /proc into the container/host path the flag points at","Check permissions: the exporter user must be able to stat the directory","Verify with `ls $(your-procfs-path)/sys` that the filesystem is really procfs"],"exampleFix":"// before\nnode_exporter --collector.sysctl --path.procfs=/host/procs\n// after\nnode_exporter --collector.sysctl --path.procfs=/host/proc","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(*procPath); err != nil { return fmt.Errorf(\"procfs path %q unusable: %w\", *procPath, err) }","typeGuard":null,"tryCatchPattern":"c, err := NewSysctlCollector(logger)\nif err != nil {\n    logger.Warn(\"sysctl collector disabled\", \"err\", err)\n    c = nil\n}","preventionTips":["Always sanity-check --path.procfs with ls before enabling the sysctl collector","In containers, explicitly mount /proc (or host /proc) at the path the flag expects","Remember sysctl is defaultDisabled; only enable it where procfs is guaranteed"],"tags":["linux","sysctl","procfs","filesystem","startup"],"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"}