prometheus/node_exporter · error

unable to list all processes

Error message

unable to list all processes: %w

What it means

getAllocatedThreads calls c.fs.AllProcs() to enumerate /proc and wraps any error as 'unable to list all processes'. AllProcs reads the /proc directory listing (and related stat data), so this indicates the process table could not be enumerated at all.

Solutions

  1. Inspect the wrapped cause; if it is a permission error, fix filesystem permissions for the exporter user on the procfs path.
  2. Verify --path.procfs points to a live procfs mount containing numeric PID directories (ls /proc | grep -E '^[0-9]+$').
  3. In tests, ensure fixtures are unpacked (make test) and the fs handle is built from the fixture path.
  4. Retry the scrape; a transient readdir failure (e.g. during heavy pid churn) often resolves on the next scrape.
Defensive patterns

Strategy: validation

Validate before calling

// before constructing/using the collector
entries, err := os.ReadDir(*procPath)
if err != nil {
    log.Printf("cannot list %s: %v", *procPath, err)
} else {
    numeric := 0
    for _, e := range entries {
        if _, err := strconv.Atoi(e.Name()); err == nil {
            numeric++
        }
    }
    if numeric == 0 {
        log.Printf("%s has no pid directories; is it a real procfs?", *procPath)
    }
}

Try / catch

if err := c.Update(ch); err != nil {
    if strings.Contains(err.Error(), "unable to list all processes") {
        log.Printf("procfs enumeration broken, check --path.procfs and permissions: %v", err)
    }
}

Prevention

When it happens

Trigger: fs.AllProcs() returns an error during Update()'s call to getAllocatedThreads — the procfs handle points to an unreadable or non-proc directory, or a directory read failed with an error other than a missing entry.

Common situations: --path.procfs pointing at a wrong or empty directory (e.g. stale fixture path); procfs mounted with hidepid and restricted readdir; EPERM/EACCES on directory traversal for the exporter user.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at collector/processes_linux.go:119

	for state := range threadStates {
		ch <- prometheus.MustNewConstMetric(c.threadsState, prometheus.GaugeValue, float64(threadStates[state]), state)
	}

	pidM, err := readUintFromFile(procFilePath("sys/kernel/pid_max"))
	if err != nil {
		return fmt.Errorf("unable to retrieve limit number of maximum pids allowed: %w", err)
	}
	ch <- prometheus.MustNewConstMetric(c.pidUsed, prometheus.GaugeValue, float64(pids))
	ch <- prometheus.MustNewConstMetric(c.pidMax, prometheus.GaugeValue, float64(pidM))

	return nil
}

func (c *processCollector) getAllocatedThreads() (int, map[string]int32, int, map[string]int32, error) {
	p, err := c.fs.AllProcs()
	if err != nil {
		return 0, nil, 0, nil, fmt.Errorf("unable to list all processes: %w", err)
	}
	pids := 0
	thread := 0
	procStates := make(map[string]int32)
	threadStates := make(map[string]int32)

	for _, pid := range p {
		stat, err := pid.Stat()
		if err != nil {
			// PIDs can vanish between getting the list and getting stats.
			if c.isIgnoredError(err) {
				c.logger.Debug("file not found when retrieving stats for pid", "pid", pid.PID, "err", err)
				continue
			}
			c.logger.Debug("error reading stat for pid", "pid", pid.PID, "err", err)
			return 0, nil, 0, nil, fmt.Errorf("error reading stat for pid %d: %w", pid.PID, err)
		}
		pids++

View on GitHub (pinned to 17ddd77c59)