{"record":{"id":"30666aa5ed5f7095","repo":"prometheus/node_exporter","slug":"failed-to-open-sysfs-w-30666a","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/thermal_zone_linux.go","lineNumber":48,"sourceCode":"const thermalZone = \"thermal_zone\"\n\ntype thermalZoneCollector struct {\n\tfs                    sysfs.FS\n\tcoolingDeviceCurState *prometheus.Desc\n\tcoolingDeviceMaxState *prometheus.Desc\n\tzoneTemp              *prometheus.Desc\n\tlogger                *slog.Logger\n}\n\nfunc init() {\n\tregisterCollector(\"thermal_zone\", defaultEnabled, NewThermalZoneCollector)\n}\n\n// NewThermalZoneCollector returns a new Collector exposing kernel/system statistics.\nfunc NewThermalZoneCollector(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 &thermalZoneCollector{\n\t\tfs: fs,\n\t\tzoneTemp: prometheus.NewDesc(\n\t\t\tprometheus.BuildFQName(namespace, thermalZone, \"temp\"),\n\t\t\t\"Zone temperature in Celsius\",\n\t\t\t[]string{\"zone\", \"type\"}, nil,\n\t\t),\n\t\tcoolingDeviceCurState: prometheus.NewDesc(\n\t\t\tprometheus.BuildFQName(namespace, coolingDevice, \"cur_state\"),\n\t\t\t\"Current throttle state of the cooling device\",\n\t\t\t[]string{\"name\", \"type\"}, nil,\n\t\t),\n\t\tcoolingDeviceMaxState: prometheus.NewDesc(\n\t\t\tprometheus.BuildFQName(namespace, coolingDevice, \"max_state\"),\n\t\t\t\"Maximum throttle state of the cooling device\",\n\t\t\t[]string{\"name\", \"type\"}, nil,","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/thermal_zone_linux.go#L30-L66","documentation":"NewThermalZoneCollector wraps the error returned by sysfs.NewFS when the /sys mount point (path given by --path.sysfs) cannot be opened. sysfs.NewFS fails when the path does not exist or is not a directory, so the collector cannot be constructed at registration time. This is a constructor error, not a scrape-time error.","triggerScenarios":"Calling NewThermalZoneCollector (node_exporter --collector.thermal_zone) when *sysPath points to a nonexistent or non-directory path, e.g. --path.sysfs=/wrong/path.","commonSituations":"Running node_exporter in a container where /sys is not mounted, misconfigured --path.sysfs flag in systemd unit files, or host-path remapping under Kubernetes that hides the real /sys.","solutions":["Verify /sys exists and is a directory on the target host (ls -ld /sys).","Correct the --path.sysfs flag to point at the real sysfs mount.","In containers/Kubernetes, mount /sys from the host into the exporter container.","If the platform has no sysfs, don't enable the thermal_zone collector."],"exampleFix":"// before\nnode_exporter --path.sysfs=/host/wrong-sys\n// after\nnode_exporter --path.sysfs=/sys  # or the correctly mounted host path","handlingStrategy":"validation","validationCode":"if fi, err := os.Stat(sysfsPath); err != nil || !fi.IsDir() {\n    // sysfs unavailable: don't enable the thermal_zone collector\n}","typeGuard":null,"tryCatchPattern":"c, err := collector.NewThermalZoneCollector(logger)\nif err != nil {\n    logger.Warn(\"thermal_zone collector disabled\", \"err\", err)\n} else {\n    registry.MustRegister(c)\n}","preventionTips":["Validate --path.sysfs exists before enabling sysfs-based collectors.","Mount /sys in containerized deployments.","Use default flag values unless you deliberately relocated pseudo-filesystems.","Register collectors conditionally so one unavailable fs doesn't kill startup."],"tags":["linux","sysfs","collector-init","filesystem"],"backgroundTag":"file-not-found","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"}