prometheus/node_exporter · error

failed to open procfs

Error message

failed to open procfs: %w

What it means

sockstatCollector.Update wraps errors from procfs.NewFS(*procPath) with 'failed to open procfs'. Unlike most collectors, this one constructs the procfs handle on every scrape, so a bad proc path makes every scrape of node_sockstat metrics fail.

Solutions

  1. Correct --path.procfs to a mounted procfs (default /proc)
  2. Mount /proc in the container
  3. Confirm the default path works by running with --path.procfs=/proc

Example fix

// before
node_exporter --path.procfs=/nonexistent/proc
// after
node_exporter --path.procfs=/proc
Defensive patterns

Strategy: validation

Validate before calling

func ensureProcfs(path string) error {
	if _, err := os.Stat(filepath.Join(path, "net")); err != nil {
		return fmt.Errorf("%q is not a mounted procfs: %w", path, err)
	}
	return nil
}

Try / catch

if err := collector.Update(ch); err != nil {
	if strings.Contains(err.Error(), "failed to open procfs") {
		logger.Warn("sockstat scrape failed: procfs unavailable", "err", err)
	} else {
		return err
	}
}

Prevention

When it happens

Trigger: During Update, --path.procfs points to a nonexistent or invalid directory; every scrape of the sockstat collector returns this error.

Common situations: /proc not mounted in containers; --path.procfs misconfigured for chroot/isolated environments; proc mount disappearing at runtime.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at collector/sockstat_linux.go:51

var pageSize = os.Getpagesize()

type sockStatCollector struct {
	logger *slog.Logger
}

func init() {
	registerCollector(sockStatSubsystem, defaultEnabled, NewSockStatCollector)
}

// NewSockStatCollector returns a new Collector exposing socket stats.
func NewSockStatCollector(logger *slog.Logger) (Collector, error) {
	return &sockStatCollector{logger}, nil
}

func (c *sockStatCollector) Update(ch chan<- prometheus.Metric) error {
	fs, err := procfs.NewFS(*procPath)
	if err != nil {
		return fmt.Errorf("failed to open procfs: %w", err)
	}

	// If IPv4 and/or IPv6 are disabled on this kernel, handle it gracefully.
	stat4, err := fs.NetSockstat()
	switch {
	case err == nil:
	case errors.Is(err, os.ErrNotExist):
		c.logger.Debug("IPv4 sockstat statistics not found, skipping")
	default:
		return fmt.Errorf("failed to get IPv4 sockstat data: %w", err)
	}

	stat6, err := fs.NetSockstat6()
	switch {
	case err == nil:
	case errors.Is(err, os.ErrNotExist):
		c.logger.Debug("IPv6 sockstat statistics not found, skipping")
	default:

View on GitHub (pinned to 17ddd77c59)