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

  1. Verify the flag: `--path.sysfs=/sys` and that the directory exists (`ls /sys/class/net`).
  2. Mount sysfs in the container or point the flag at the real sysfs location.
  3. Check mount options/permissions; the wrapped %w error names the precise OS cause.
  4. 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

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


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)