prometheus/node_exporter · error

failed to open procfs

Error message

failed to open procfs: %w

What it means

NewZoneinfoCollector initializes a procfs client rooted at the --path.procfs flag value; if procfs.NewFS fails (directory missing or unreadable) the collector cannot read /proc/zoneinfo, so it returns this wrapped error instead of a collector. Node_exporter surfaces it at startup as a failed enabled collector.

Solutions

  1. Verify the path given to --path.procfs exists and contains procfs files (zoneinfo)
  2. Ensure /proc is mounted in the container (--volume /proc:/host/proc:ro and --path.procfs=/host/proc)
  3. Disable the zoneinfo collector (--collector.zoneinfo) if the environment has no zone stats
  4. Check mount namespace/permissions so the process can read the procfs directory

Example fix

// before
node_exporter --collector.zoneinfo --path.procfs=/host/proc
# fails if /host/proc is not mounted
// after
node_exporter --collector.zoneinfo --path.procfs=/proc
# or mount: docker run -v /proc:/host/proc:ro ...
Defensive patterns

Strategy: try-catch

Validate before calling

if st, err := os.Stat(*procPath); err != nil || !st.IsDir() {
    // do not enable the zoneinfo collector
}

Try / catch

collector, err := NewZoneinfoCollector(logger)
if err != nil {
    logger.Warn("zoneinfo collector unavailable", "err", err)
    collector = nil
}

Prevention

When it happens

Trigger: Starting node_exporter with the zoneinfo collector enabled while *procPath points to a nonexistent or non-procfs directory (e.g. --path.procfs=/proc on a non-Linux container, or a bad chroot/mount).

Common situations: Running the exporter in a container without /proc mounted; a typo in --path.procfs; collecting from a remote filesystem mount that lacks /proc/zoneinfo; restricted mount namespaces.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07). Data as JSON: /api/errors/71802e133e406be4. Report an issue: GitHub.

Appendix: source

Thrown at collector/zoneinfo_linux.go:42

const zoneinfoSubsystem = "zoneinfo"

type zoneinfoCollector struct {
	gaugeMetricDescs   map[string]*prometheus.Desc
	counterMetricDescs map[string]*prometheus.Desc
	logger             *slog.Logger
	fs                 procfs.FS
}

func init() {
	registerCollector("zoneinfo", defaultDisabled, NewZoneinfoCollector)
}

// NewZoneinfoCollector returns a new Collector exposing zone stats.
func NewZoneinfoCollector(logger *slog.Logger) (Collector, error) {
	fs, err := procfs.NewFS(*procPath)
	if err != nil {
		return nil, fmt.Errorf("failed to open procfs: %w", err)
	}
	return &zoneinfoCollector{
		gaugeMetricDescs:   createGaugeMetricDescriptions(),
		counterMetricDescs: createCounterMetricDescriptions(),
		logger:             logger,
		fs:                 fs,
	}, nil
}

func (c *zoneinfoCollector) Update(ch chan<- prometheus.Metric) error {
	metrics, err := c.fs.Zoneinfo()
	if err != nil {
		return fmt.Errorf("couldn't get zoneinfo: %w", err)
	}
	for _, metric := range metrics {
		node := metric.Node
		zone := metric.Zone
		metricStruct := reflect.ValueOf(metric)

View on GitHub (pinned to 17ddd77c59)