prometheus/node_exporter · error

failed to open procfs

Error message

failed to open procfs: %w

What it means

NewNFSdCollector constructs the collector by calling nfs.NewFS(*procPath), which validates that the given procfs mount point exists and looks like a proc filesystem. If it cannot be opened (missing path, wrong path flag, or not a procfs mount), the constructor returns this wrapped error and no collector is created. This is a startup-time failure, not a scrape-time one.

Solutions

  1. Pass the correct procfs location: --path.procfs=/proc (or the mounted host path in containers).
  2. Verify the directory exists and is a procfs mount: 'mount | grep proc' and 'ls /proc/net/rpc/nfsd'.
  3. In containers, mount the host proc read-only, e.g. -v /proc:/host/proc:ro, and point --path.procfs at it.
  4. Check the wrapped cause in the error to distinguish ENOENT (wrong path) from other failures.

Example fix

// before: wrong proc path inside container
//   ./node_exporter --collector.nfsd
// after: mount and point at host procfs
//   docker run -v /proc:/host/proc:ro node-exporter \
//     --path.procfs=/host/proc --collector.nfsd
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate proc path before constructing the collector
st, err := os.Stat(filepath.Join(*procPath, "net/rpc/nfsd"))
if err != nil || st.IsDir() {
    log.Fatalf("invalid --path.procfs (%s): nfsd stats unavailable", *procPath)
}

Try / catch

// constructor errors are fatal at startup; check and fail fast
fs, err := nfs.NewFS(*procPath)
if err != nil {
    return nil, fmt.Errorf("failed to open procfs: %w", err) // surface wrapped cause
}

Prevention

When it happens

Trigger: Calling NewNFSdCollector (directly or via node_exporter startup) when the --path.procfs flag points to a nonexistent directory or a directory that is not a procfs mount, causing nfs.NewFS to fail.

Common situations: Running node_exporter in a container without mounting the host /proc and forgetting --path.procfs=/host/proc; typo in --path.procfs; running on a system where the proc path was overridden for testing to an invalid value.

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/2d9e8757939acab1. Report an issue: GitHub.

Appendix: source

Thrown at collector/nfsd_linux.go:48

type nfsdCollector struct {
	fs           nfs.FS
	requestsDesc *prometheus.Desc
	logger       *slog.Logger
}

func init() {
	registerCollector("nfsd", defaultEnabled, NewNFSdCollector)
}

const (
	nfsdSubsystem = "nfsd"
)

// NewNFSdCollector returns a new Collector exposing /proc/net/rpc/nfsd statistics.
func NewNFSdCollector(logger *slog.Logger) (Collector, error) {
	fs, err := nfs.NewFS(*procPath)
	if err != nil {
		return nil, fmt.Errorf("failed to open procfs: %w", err)
	}

	return &nfsdCollector{
		fs: fs,
		requestsDesc: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, nfsdSubsystem, "requests_total"),
			"Total number NFSd Requests by method and protocol.",
			[]string{"proto", "method"}, nil,
		),
		logger: logger,
	}, nil
}

// Update implements Collector.
func (c *nfsdCollector) Update(ch chan<- prometheus.Metric) error {
	stats, err := c.fs.ServerRPCStats()
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {

View on GitHub (pinned to 17ddd77c59)