prometheus/node_exporter · critical
failed to open sysfs
Error message
failed to open sysfs: %w
What it means
makeEthtoolCollector, the internal constructor used by NewEthtoolCollector (and the test constructor), first opens sysfs via sysfs.NewFS(*sysPath) (default /sys). If that path cannot be opened as a sysfs filesystem, the constructor returns 'failed to open sysfs' and node_exporter fails to create the ethtool collector. Like the procfs counterpart, this is nearly always a bad --path.sysfs flag or missing /sys.
Solutions
- Verify the flag: `--path.sysfs=/sys` and that the directory exists (`ls /sys/class/net`).
- Mount sysfs in the container or point the flag at the real sysfs location.
- Check mount options/permissions; the wrapped %w error names the precise OS cause.
- Disable the ethtool collector (--collector.ethtool=false) if sysfs is unavailable by design.
Example fix
// before: wrong path node_exporter --path.sysfs=/syss // after node_exporter --path.sysfs=/sys
Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
function sysfsLooksValid(p = '/sys') {
return fs.existsSync(p) && fs.statSync(p).isDirectory() && fs.existsSync(`${p}/class/net`);
}
if (!sysfsLooksValid()) console.error('--path.sysfs target invalid; ethtool collector will fail to start'); Try / catch
try {
await startNodeExporter({ sysPath: '/sys' });
} catch (e) {
if (String(e).includes('failed to open sysfs')) {
console.error('Bad --path.sysfs; verify /sys is mounted and the flag is correct');
} else throw e;
} Prevention
- Pass --path.sysfs=/sys explicitly in container/deployment manifests.
- Ensure sysfs is mounted (privileged or proper volume mount) in containers.
- Validate flag values with a startup smoke test.
When it happens
Trigger: makeEthtoolCollector invoked with --path.sysfs pointing at a nonexistent or non-sysfs directory; environment without /sys mounted.
Common situations: Typo in --path.sysfs; minimal containers/chroots without sysfs; running inside namespaces where sysfs was remounted away; permission restrictions on the mount.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- failed to open sysfs
- failed to open procfs
- failed to initialize ethtool library
- failed to open procfs
- failed to open procfs
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/87d996930293acca.
Report an issue: GitHub.
Appendix: source
Thrown at collector/ethtool_linux.go:89
type ethtoolCollector struct {
fs sysfs.FS
entries map[string]*prometheus.Desc
entriesMutex sync.Mutex
ethtool Ethtool
deviceFilter deviceFilter
infoDesc *prometheus.Desc
metricsPattern *regexp.Regexp
logger *slog.Logger
}
// makeEthtoolCollector is the internal constructor for EthtoolCollector.
// This allows NewEthtoolTestCollector to override its .ethtool interface
// for testing.
func makeEthtoolCollector(logger *slog.Logger) (*ethtoolCollector, error) {
fs, err := sysfs.NewFS(*sysPath)
if err != nil {
return nil, fmt.Errorf("failed to open sysfs: %w", err)
}
e, err := ethtool.NewEthtool()
if err != nil {
return nil, fmt.Errorf("failed to initialize ethtool library: %w", err)
}
if *ethtoolDeviceInclude != "" {
logger.Info("Parsed flag --collector.ethtool.device-include", "flag", *ethtoolDeviceInclude)
}
if *ethtoolDeviceExclude != "" {
logger.Info("Parsed flag --collector.ethtool.device-exclude", "flag", *ethtoolDeviceExclude)
}
if *ethtoolIncludedMetrics != "" {
logger.Info("Parsed flag --collector.ethtool.metrics-include", "flag", *ethtoolIncludedMetrics)
}
// Pre-populate some common ethtool metrics.View on GitHub (pinned to 17ddd77c59)